Merged with mirror-3.14

This commit is contained in:
Dirk Zimoch
2010-07-07 19:42:08 +02:00
18 changed files with 1301 additions and 641 deletions

View File

@@ -19,6 +19,29 @@ Added Soft Channel device support.
Added SIOL link and proper simulation mode for Soft Channel support.
Added MPST, APST and HASH fields for monitor on change support like in waveform record.
<h4>devLib cleanup</h4>
<ul>
<li>Add VME connect/disconnect IRQ calls to the "virtual os" table</li>
<li>It is now possible to compile all devLib code on targets without runtime
support</li>
<li>All internal functions are made static. Some were not before.</li>
<li>Move VME calls to <tt>devLibVME.h</tt>. <tt>devLib.h</tt> contains general
defintions and error codes.</li>
<li>For compatibility <tt>devLib.h</tt> includes <tt>devLibVME.h</tt> unless the
macro <tt>NO_DEVLIB_COMPAT</tt> is defined.</li>
<li>The "virtual os" table was renamed from <tt>pdevLibVirtualOS</tt> to
<tt>pdevLibVME</tt> reflecting the fact that other bus types will need seperate
tables.</li>
<li>The "virtual os" table API has been moved to a seperate header file,
<tt>devLibVMEImpl.h</tt>.</li>
</ul>
<h4>DTYP and INP/OUT order</h4>
<p>The fields DTYP and INP/OUT can now be specified in any order.</p>
<h4>Rewrite epicsThreadOnce()</h4>
<p>Michael Davidsaver suggested a better implementation of epicsThreadOnce()

View File

@@ -85,7 +85,7 @@ DIRS += gdd
gdd_DEPEND_DIRS = ca
DIRS += cas
cas_DEPEND_DIRS = gdd
cas_DEPEND_DIRS = gdd dbStatic
DIRS += excas
excas_DEPEND_DIRS = cas as registry

View File

@@ -144,12 +144,13 @@ int main(int argc, char **argv)
if(*pend!='"') errExit("Illegal Header");
len = pend - pbeg;
if(len<=1) errExit("Illegal Header");
pname = calloc(len,sizeof(char));
pname = calloc(len+1,sizeof(char));
if(!pname) {
fprintf(stderr,"calloc failed while processing line %d\n",linenum);
exit(-1);
}
strncpy(pname,pbeg,len);
pname[len]='\0';
pbeg = pend + 1;
if(getNumber(&pbeg,&value)) errExit("Illegal Header");
brkCreateInfo.engLow = value;

View File

@@ -29,6 +29,7 @@ ifeq ($(findstring $(OS_CLASS),WIN32 cygwin32),)
PERL_SCRIPTS += cainfo.pl
PERL_SCRIPTS += caput.pl
PERL_SCRIPTS += caget.pl
PERL_SCRIPTS += capr.pl
PERL_SCRIPTS += camonitor.pl
PERL_MODULES += CA.pm

423
src/cap5/capr.pl Normal file
View File

@@ -0,0 +1,423 @@
#!/usr/bin/perl -w
#######################################################################
#
# capr: A program that attempts to do a "dbpr" command via channel
# access.
#
#######################################################################
use strict;
use FindBin qw($Bin);
use lib "$Bin/../../lib/perl";
use Getopt::Std;
use EPICS::Path;
use CA;
######### Globals ##########
our ($opt_h, $opt_f, $opt_r);
our $opt_d = $ENV{EPICS_CAPR_DBD_FILE} || "$Bin/../../dbd/softIoc.dbd";
our $opt_w = 1;
my %record = (); # Empty hash to put dbd data in
my $iIdx = 0; # Array indexes for interest, data type and base
my $tIdx = 1;
my $bIdx = 2;
my %device = (); # Empty hash to record which rec types have device support
# EPICS field types
my %fieldType = (
DBF_CHAR => 'DBF_CHAR',
DBF_UCHAR => 'DBF_CHAR',
DBF_DOUBLE => 'DBF_FLOAT',
DBF_FLOAT => 'DBF_FLOAT',
DBF_LONG => 'DBF_LONG',
DBF_SHORT => 'DBF_LONG',
DBF_ULONG => 'DBF_LONG',
DBF_USHORT => 'DBF_LONG',
DBF_DEVICE => 'DBF_STRING',
DBF_ENUM => 'DBF_STRING',
DBF_FWDLINK => 'DBF_STRING',
DBF_INLINK => 'DBF_STRING',
DBF_MENU => 'DBF_STRING',
DBF_OUTLINK => 'DBF_STRING',
DBF_STRING => 'DBF_STRING',
DBF_NOACCESS => 'DBF_NOACCESS',
);
# globals for sub caget
my %callback_data;
my %timed_out;
my $callback_incomplete;
######### Main program ############
HELP_MESSAGE() unless getopts('hd:f:rw:');
HELP_MESSAGE() if $opt_h;
die "File $opt_d not found. (\"capr.pl -h\" gives help)\n"
unless -f $opt_d;
parseDbd($opt_d);
print "Using $opt_d\n\n";
# Print a list of record types
if ($opt_r) {
print ("Record types found:\n");
printList(0);
exit;
}
# Print the fields defined for given record
if ($opt_f) {
printRecordList($opt_f);
exit;
}
HELP_MESSAGE() unless @ARGV;
$_ = shift;
if (@ARGV) {
# Drop any ".FIELD" part
s/\. \w+ $//x;
printRecord($_, @ARGV);
} else {
if (m/^ \s* ([]+:;<>0-9A-Za-z[-]+) (?:\. \w+)? \s* , \s* (\d+) \s* $/x) {
# Recognizes ",n" as an interest leve, drops any ".FIELD" part
printRecord($1, $2);
} else {
# Drop any ".FIELD" part
s/\. \w+ $//x;
printRecord($_, 0);
}
}
########## End of main ###########
# parseDbd
# Takes given dbd file and parses it to produce a hash table of record types
# giving their fields, and for each field its interest level and data type.
# usage: parseDbd("fileName");
# Output goes to the global %record, a hash of references to other hashes
# containing the fields of each record type. Those hash values (keyed by
# field name) are references to arrays containing the interest level, data
# type and number base of the field.
sub parseDbd {
my $dbdFile = shift;
open(DBD, "< $dbdFile") or die "Can't open file $dbdFile: $!\n";
my @dbd = <DBD>;
close(DBD) or die "Can't close $dbdFile: $!\n";
my $i = 1;
my $level = 0;
my $isArecord = 0;
my $isAfield = 0;
my $thisRecord;
my $thisField;
my $thisType;
my $field = {};
my $interest = 0;
my $thisBase = 'DECIMAL';
while (@dbd) {
$_ = shift @dbd;
chomp;
if ( m/recordtype \s* \( \s* (\w+) \)/x ) {
die "File format error at line $i of file\n $opt_d\n"
unless $level == 0;
$isArecord = 1;
$thisRecord = $1;
}
elsif ( m/field \s* \( \s* (\w+) \s* , \s* (\w+) \s* \)/x ) {
die "File format error at line $i of file\n $opt_d\n"
unless $level == 1 && $isArecord;
$thisField = $1;
$thisType = $2;
$isAfield = 1;
}
elsif ( m/interest \s* \( \s* (\w+) \s* \)/x ) {
die "File format error at line $i of file\n $opt_d\n"
unless $level == 2 && $isAfield;
$interest = $1;
}
elsif ( m/base \s* \( \s* (\w+) \s* \)/x ) {
die "File format error at line $i of file\n $opt_d\n"
unless $level == 2 && $isAfield;
$thisBase = $1;
}
elsif ( m/device \s* \( (\w+) \s* ,/x ) {
die "File format error at line $i of file\n $opt_d\n"
unless $level == 0;
$device{$1}++;
}
if ( m/\{/ ) {
$level++;
}
if ( m/\}/ ) {
if ($level == 2 && $isAfield) {
my $params = [];
$params->[$iIdx] = $interest;
$params->[$tIdx] = $thisType;
$params->[$bIdx] = $thisBase;
$field->{$thisField} = $params;
$isAfield = 0;
$interest = 0; # reset default
$thisBase = 'DECIMAL'; # reset default
}
elsif ($level == 1 && $isArecord) {
$isArecord = 0;
$record{$thisRecord} = $field;
$field = {}; # start another hash
}
$level--;
}
$i++;
}
}
# Given a record name, attempts to find the record and its type.
# Usage: $recordType = getRecType("recordName");
sub getRecType {
my $arg = shift;
my $name = "$arg.RTYP";
my $fields_read = caget($name);
die "Could not determine record type of $arg\n"
unless $fields_read == 1;
return $callback_data{$name};
}
# Given the record type and field, returns the interest level, data type
# and number base for the field
# Usage: ($dataType, $interest, $base) = getFieldParams($recType, $field);
sub getFieldParams {
my ($recType, $field) = @_;
my $params = $record{$recType}{$field} or
die "Can't find params for $recType.$field";
exists($fieldType{$params->[$tIdx]}) ||
die "Field data type $field for $recType not found in dbd file --";
exists($params->[$iIdx]) ||
die "Interest level for $field in $recType not found in dbd file --";
my $fType = $fieldType{$params->[$tIdx]};
my $fInterest = $params->[$iIdx];
my $fBase = $params->[$bIdx];
return ($fType, $fInterest, $fBase);
}
# Prints field name and data for given field. Formats output so
# that fields align in to 4 columns. Tries to imitate dbpf format
# Usage: printField( $fieldName, $data, $dataType, $base, $firstColumnPosn)
sub printField {
my ($fieldName, $fieldData, $dataType, $base, $col) = @_;
my $screenWidth = 80;
my ($outStr, $wide);
my $field = "$fieldName:";
if ( $dataType eq 'DBF_STRING' ) {
$outStr = sprintf('%-5s %s', $field, $fieldData);
} elsif ( $base eq 'HEX' ) {
my $val = ( $dataType eq 'DBF_CHAR' ) ? ord($fieldData) : $fieldData;
$outStr = sprintf('%-5s 0x%x', $field, $val);
} elsif ( $dataType eq 'DBF_DOUBLE' || $dataType eq 'DBF_FLOAT' ) {
$outStr = sprintf('%-5s %.8f', $field, $fieldData);
} elsif ( $dataType eq 'DBF_CHAR' ) {
$outStr = sprintf('%-5s %d', $field, ord($fieldData));
}else {
# DBF_LONG, DBF_SHORT, DBF_UCHAR, DBF_ULONG, DBF_USHORT
$outStr = sprintf('%-5s %d', $field, $fieldData);
}
my $len = length($outStr);
if ($len <= 20) { $wide = 20; }
elsif ( $len <= 40 ) { $wide = 40; }
elsif ( $len <= 60 ) { $wide = 60; }
else { $wide = 80;}
my $pad = $wide - $len;
$col += $wide;
if ($col > $screenWidth ) {
print("\n");
$col = $wide;
}
print $outStr, ' ' x $pad;
return $col;
}
# Query for a list of fields simultaneously.
# The results are filled in the the %callback_data global hash
# and the result of the operation is the number of read pvs
#
# NOTE: Not re-entrant because results are written to global hash
# %callback_data
#
# Usage: $fields_read = caget( @pvlist )
sub caget {
my @chans = map { CA->new($_); } @_;
#clear results;
%callback_data = ();
%timed_out = ();
eval { CA->pend_io($opt_w); };
if ($@) {
if ($@ =~ m/^ECA_TIMEOUT/) {
my $err = (@chans > 1) ? 'some PV(s)' : '"' . $chans[0]->name . '"';
print "Channel connect timed out: $err not found.\n";
foreach my $chan (@chans) {
$timed_out{$chan->name} = $chan->is_connected;
}
@chans = grep { $_->is_connected } @chans;
} else {
die $@;
}
}
map {
my $type;
$type = $_->field_type;
$_->get_callback(\&caget_callback, $type);
} @chans;
my $fields_read = @chans;
$callback_incomplete = @chans;
CA->pend_event(0.1) while $callback_incomplete;
return $fields_read;
}
sub caget_callback {
my ($chan, $status, $data) = @_;
die $status if $status;
$callback_data{$chan->name} = $data;
$callback_incomplete--;
}
# Given record name and interest level prints data from record fields
# that are at or below the interest level specified.
# Usage: printRecord($recordName, $interestLevel)
sub printRecord {
my ($name, $interest) = @_;
my $recType = getRecType($name);
print("Record $name type $recType\n");
die "Record type $recType not found\n"
unless exists $record{$recType};
#capture list of fields
my @readlist = (); #fields to read via CA
my @fields_pr = (); #fields for print-out
my @ftypes = (); #types, from parser
my @bases = (); #bases, from parser
foreach my $field (sort keys %{$record{$recType}}) {
# Skip DTYP field if this rec type doesn't have device support defined
if ($field eq 'DTYP' && !(exists($device{$recType}))) { next; }
my ($fType, $fInterest, $base) = getFieldParams($recType, $field);
unless( $fType eq 'DBF_NOACCESS' ) {
if ($interest >= $fInterest ) {
my $fToGet = "$name.$field";
push @fields_pr, $field;
push @readlist, $fToGet;
push @ftypes, $fType;
push @bases, $base;
}
}
}
my $fields_read = caget( @readlist );
# print while iterating over lists gathered
my $col = 0;
for (my $i=0; $i < scalar @readlist; $i++) {
my $field = $fields_pr[$i];
my $fToGet = $readlist[$i];
my ($fType, $data, $base);
if ($timed_out{$fToGet}) {
$fType = $fieldType{DBF_STRING};
$data = '<timeout>';
}
else {
$fType = $ftypes[$i];
$base = $bases[$i];
$data = $callback_data{$fToGet};
}
$col = printField($field, $data, $fType, $base, $col);
}
print("\n"); # Final newline
}
# Prints list of record types found in dbd file. If level > 0
# then the fields of that record type, their interest levels and types are
# also printed.
# Diagnostic routine, usage: void printList(level);
sub printList {
my $level = shift;
foreach my $rkey (sort keys(%record)) {
print(" $rkey\n");
if ($level > 0) {
foreach my $fkey (keys %{$record{$rkey}}) {
print("\tField $fkey - interest $record{$rkey}{$fkey}[$iIdx] ");
print("- type $record{$rkey}{$fkey}[$tIdx] ");
print("- base $record{$rkey}{$fkey}[$bIdx]\n");
}
}
}
}
# Prints list of fields with interest levels for given record type
# Diagnostic routine, usage: void printRecordList("recordType");
sub printRecordList {
my $type = shift;
if (exists($record{$type}) ) {
print("Record type - $type\n");
foreach my $fkey (sort keys %{$record{$type}}) {
printf('%-4s', $fkey);
printf(" interest = $record{$type}{$fkey}[$iIdx]");
printf(" type = %-12s ",$record{$type}{$fkey}[$tIdx]);
print (" base = $record{$type}{$fkey}[$bIdx]\n");
}
}
else {
print("Record type $type not defined in dbd file $opt_d\n");
}
}
sub HELP_MESSAGE {
print STDERR "\n",
"Usage: capr.pl -h\n",
" capr.pl [-d file.dbd] [-w seconds] -r\n",
" capr.pl [-d file.dbd] [-w seconds] -f record_type\n",
" capr.pl [-d file.dbd] [-w seconds] record_name [interest]\n",
"Description:\n",
" Attempts to perform a \"dbpr\" record print via channel access for \n",
" record_name at an interest level which defaults to level 0.\n\n",
" The -r or -f options cause it to print record type or field lists.\n",
"\n",
"Options:\n",
" -h Prints this help message.\n",
" -r Lists all record types in the dbd file.\n",
" -f record_type: Lists all fields plus their interest level, data type\n",
" and number base for the given record_type.\n",
" -d file.dbd: The dbd file containing record type definitions.\n",
" This can be set using the EPICS_CAPR_DBD_FILE environment variable.\n",
" Currently ", AbsPath($opt_d), "\n",
" -w seconds: CA connection timeout, currently $opt_w\n",
"\n";
exit 1;
}

View File

@@ -246,15 +246,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_string *pold = (struct dbr_sts_string *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
DBSTRING *pvalue = (DBSTRING *)pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_STRING, pold->value, &options,
@@ -268,15 +268,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_int *pold = (struct dbr_sts_int *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_short_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
@@ -289,15 +289,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_float *pold = (struct dbr_sts_float *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_float_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
@@ -310,15 +310,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_enum *pold = (struct dbr_sts_enum *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_enum_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
@@ -331,15 +331,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_char *pold = (struct dbr_sts_char *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_char_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
@@ -352,15 +352,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_long *pold = (struct dbr_sts_long *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_long_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
@@ -373,15 +373,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_sts_double *pold = (struct dbr_sts_double *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
dbr_double_t *pvalue = &pold->value;
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->status = newSt.status;
pold->severity = newSt.severity;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
@@ -396,16 +396,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
DBSTRING *pvalue = (DBSTRING *)(pold->value);
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_STRING, pold->value, &options,
@@ -420,16 +420,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_short_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
@@ -443,16 +443,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_float_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
@@ -466,16 +466,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_enum_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_ENUM, &pold->value, &options,
@@ -489,16 +489,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_char_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_CHAR, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_CHAR, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_CHAR, &pold->value, &options,
@@ -512,16 +512,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_long_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
@@ -535,16 +535,16 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRtime
} new;
} newSt;
dbr_double_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_TIME;
nRequest = 0;
status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->stamp = new.time; /* structure copy */
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->stamp = newSt.time; /* structure copy */
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
@@ -563,23 +563,23 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRunits
DBRgrLong
DBRalLong
} new;
} newSt;
dbr_short_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
@@ -596,25 +596,25 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRprecision
DBRgrDouble
DBRalDouble
} new;
} newSt;
dbr_float_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_AL_DOUBLE;
nRequest = 0;
status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->precision = new.precision.dp;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = newSt.precision.dp;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit);
pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit);
pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit);
pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit);
pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit);
pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit);
pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);
pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);
pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);
pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
@@ -631,23 +631,23 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRunits
DBRgrLong
DBRalLong
} new;
} newSt;
dbr_char_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
@@ -663,23 +663,23 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRunits
DBRgrLong
DBRalLong
} new;
} newSt;
dbr_long_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
@@ -696,25 +696,25 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRprecision
DBRgrDouble
DBRalDouble
} new;
} newSt;
dbr_double_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_AL_DOUBLE;
nRequest = 0;
status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->precision = new.precision.dp;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = newSt.precision.dp;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
@@ -733,26 +733,26 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRgrLong
DBRctrlLong
DBRalLong
} new;
} newSt;
dbr_short_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_SHORT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_SHORT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_ctrl_limit = new.upper_ctrl_limit;
pold->lower_ctrl_limit = new.lower_ctrl_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_SHORT, &pold->value, &options,
@@ -770,27 +770,27 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRgrDouble
DBRctrlDouble
DBRalDouble
} new;
} newSt;
dbr_float_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
nRequest = 0;
status = dbGetField(paddr, DBR_FLOAT, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_FLOAT, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->precision = new.precision.dp;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = newSt.precision.dp;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = epicsConvertDoubleToFloat(new.upper_disp_limit);
pold->lower_disp_limit = epicsConvertDoubleToFloat(new.lower_disp_limit);
pold->upper_alarm_limit = epicsConvertDoubleToFloat(new.upper_alarm_limit);
pold->lower_alarm_limit = epicsConvertDoubleToFloat(new.lower_alarm_limit);
pold->upper_warning_limit = epicsConvertDoubleToFloat(new.upper_warning_limit);
pold->lower_warning_limit = epicsConvertDoubleToFloat(new.lower_warning_limit);
pold->upper_ctrl_limit = epicsConvertDoubleToFloat(new.upper_ctrl_limit);
pold->lower_ctrl_limit = epicsConvertDoubleToFloat(new.lower_ctrl_limit);
pold->upper_disp_limit = epicsConvertDoubleToFloat(newSt.upper_disp_limit);
pold->lower_disp_limit = epicsConvertDoubleToFloat(newSt.lower_disp_limit);
pold->upper_alarm_limit = epicsConvertDoubleToFloat(newSt.upper_alarm_limit);
pold->lower_alarm_limit = epicsConvertDoubleToFloat(newSt.lower_alarm_limit);
pold->upper_warning_limit = epicsConvertDoubleToFloat(newSt.upper_warning_limit);
pold->lower_warning_limit = epicsConvertDoubleToFloat(newSt.lower_warning_limit);
pold->upper_ctrl_limit = epicsConvertDoubleToFloat(newSt.upper_ctrl_limit);
pold->lower_ctrl_limit = epicsConvertDoubleToFloat(newSt.lower_ctrl_limit);
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_FLOAT, &pold->value, &options,
@@ -805,7 +805,7 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct {
DBRstatus
DBRenumStrs
} new;
} newSt;
short no_str;
dbr_enum_t *pvalue = &pold->value;
@@ -813,15 +813,15 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
/* first get status and severity */
options = DBR_STATUS | DBR_ENUM_STRS;
nRequest = 0;
status = dbGetField(paddr, DBR_ENUM, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_ENUM, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
no_str = new.no_str;
pold->status = newSt.status;
pold->severity = newSt.severity;
no_str = newSt.no_str;
if (no_str>16) no_str=16;
pold->no_str = no_str;
for (i = 0; i < no_str; i++)
strncpy(pold->strs[i], new.strs[i], sizeof(pold->strs[i]));
strncpy(pold->strs[i], newSt.strs[i], sizeof(pold->strs[i]));
/*now get values*/
options = 0;
nRequest = no_elements;
@@ -839,26 +839,26 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRgrLong
DBRctrlLong
DBRalLong
} new;
} newSt;
dbr_char_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_UCHAR, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_UCHAR, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_ctrl_limit = new.upper_ctrl_limit;
pold->lower_ctrl_limit = new.lower_ctrl_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_UCHAR, &pold->value, &options,
@@ -875,26 +875,26 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRgrLong
DBRctrlLong
DBRalLong
} new;
} newSt;
dbr_long_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_GR_LONG | DBR_CTRL_LONG |
DBR_AL_LONG;
nRequest = 0;
status = dbGetField(paddr, DBR_LONG, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_LONG, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_ctrl_limit = new.upper_ctrl_limit;
pold->lower_ctrl_limit = new.lower_ctrl_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_LONG, &pold->value, &options,
@@ -912,27 +912,27 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
DBRgrDouble
DBRctrlDouble
DBRalDouble
} new;
} newSt;
dbr_double_t *pvalue = &pold->value;
options = DBR_STATUS | DBR_UNITS | DBR_PRECISION | DBR_GR_DOUBLE |
DBR_CTRL_DOUBLE | DBR_AL_DOUBLE;
nRequest = 0;
status = dbGetField(paddr, DBR_DOUBLE, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_DOUBLE, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->precision = new.precision.dp;
strncpy(pold->units, new.units, MAX_UNITS_SIZE);
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->precision = newSt.precision.dp;
strncpy(pold->units, newSt.units, MAX_UNITS_SIZE);
pold->units[MAX_UNITS_SIZE-1] = '\0';
pold->upper_disp_limit = new.upper_disp_limit;
pold->lower_disp_limit = new.lower_disp_limit;
pold->upper_alarm_limit = new.upper_alarm_limit;
pold->upper_warning_limit = new.upper_warning_limit;
pold->lower_warning_limit = new.lower_warning_limit;
pold->lower_alarm_limit = new.lower_alarm_limit;
pold->upper_ctrl_limit = new.upper_ctrl_limit;
pold->lower_ctrl_limit = new.lower_ctrl_limit;
pold->upper_disp_limit = newSt.upper_disp_limit;
pold->lower_disp_limit = newSt.lower_disp_limit;
pold->upper_alarm_limit = newSt.upper_alarm_limit;
pold->upper_warning_limit = newSt.upper_warning_limit;
pold->lower_warning_limit = newSt.lower_warning_limit;
pold->lower_alarm_limit = newSt.lower_alarm_limit;
pold->upper_ctrl_limit = newSt.upper_ctrl_limit;
pold->lower_ctrl_limit = newSt.lower_ctrl_limit;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_DOUBLE, &pold->value, &options,
@@ -946,17 +946,17 @@ int epicsShareAPI db_get_field(struct dbAddr *paddr,
struct dbr_stsack_string *pold = (struct dbr_stsack_string *)pbuffer;
struct {
DBRstatus
} new;
} newSt;
DBSTRING *pvalue = (DBSTRING *)(pold->value);
options = DBR_STATUS;
nRequest = 0;
status = dbGetField(paddr, DBR_STRING, &new, &options, &nRequest,
status = dbGetField(paddr, DBR_STRING, &newSt, &options, &nRequest,
pfl);
pold->status = new.status;
pold->severity = new.severity;
pold->ackt = new.ackt;
pold->acks = new.acks;
pold->status = newSt.status;
pold->severity = newSt.severity;
pold->ackt = newSt.ackt;
pold->acks = newSt.acks;
options = 0;
nRequest = no_elements;
status = dbGetField(paddr, DBR_STRING, pold->value,

View File

@@ -277,6 +277,19 @@ static long setLinkType(DBENTRY *pdbentry)
plink = (DBLINK *)pdbentry->pfield;
if (plink->type == link_type) goto done;
if (plink->text)
{
/* re-parse link text when DTYP has changed */
char * link_text;
link_text = plink->text;
plink->text = NULL;
dbFreeLinkContents(plink);
plink->type = link_type;
dbPutString(pdbentry, link_text);
free(link_text);
goto done;
}
type = plink->type;
if ((type == CONSTANT || type == PV_LINK || type == DB_LINK || type == CA_LINK) &&
(link_type == CONSTANT || link_type == PV_LINK)) goto done;
@@ -331,6 +344,7 @@ void dbFreeLinkContents(struct link *plink)
epicsPrintf("dbFreeLink called but link type unknown\n");
}
if(parm && (parm != pNullString)) free((void *)parm);
if(plink->text) free(plink->text);
memset((char *)plink,0,sizeof(struct link));
}
@@ -516,14 +530,14 @@ dbDeviceMenu *dbGetDeviceMenu(DBENTRY *pdbentry)
/* Beginning of Public Routines */
#define INC_SIZE 256
void epicsShareAPI dbCatString(char **string,int *stringLength,char *new,char *separator)
void epicsShareAPI dbCatString(char **string,int *stringLength,char *src,char *separator)
{
if((*string==NULL)
|| ((strlen(*string)+strlen(new)+2) > (size_t)*stringLength)) {
|| ((strlen(*string)+strlen(src)+2) > (size_t)*stringLength)) {
char *newString;
size_t size;
size = strlen(new);
size = strlen(src);
if(*string) size += strlen(*string);
/*Make size multiple of INC_SIZE*/
size = ((size + 2 + INC_SIZE)/INC_SIZE) * INC_SIZE;
@@ -538,8 +552,8 @@ void epicsShareAPI dbCatString(char **string,int *stringLength,char *new,char *s
strcat(*string,separator);
*stringLength += strlen(separator);
}
strcat(*string,new);
*stringLength += strlen(new);
strcat(*string,src);
*stringLength += strlen(src);
}
dbBase * epicsShareAPI dbAllocBase(void)
@@ -2224,6 +2238,8 @@ long epicsShareAPI dbPutString(DBENTRY *pdbentry,const char *pstring)
errMessage(status,"in dbPutString from setLinkType");
return status;
}
/* store link text in case DTYP changes later */
plink->text = epicsStrDup(pstring);
}
if (strlen(pstring) >= sizeof(string)) {
status = S_dbLib_badField;

View File

@@ -183,6 +183,7 @@ union value{
struct link{
union value value;
short type;
char *text; /* original INP/OUT link text */
};
typedef struct link DBLINK;

View File

@@ -192,6 +192,8 @@ INC += epicsStdioRedirect.h
INC += epicsGetopt.h
INC += devLib.h
INC += devLibVME.h
INC += devLibVMEImpl.h
INC += osdVME.h
SRCS += epicsThread.cpp
@@ -230,8 +232,8 @@ SRCS += osdProcess.c
SRCS += osdNetIntf.c
SRCS += osdMessageQueue.c
SRCS += devLib.c
SRCS += devLibOSD.c
SRCS += devLibVME.c
SRCS += devLibVMEOSD.c
SRC_DIRS += $(LIBCOM)/taskwd
INC += taskwd.h

View File

@@ -1,252 +1,27 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLib.h */
/* $Id$ */
/*
* Original Author: Marty Kraimer
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
*/
#ifndef INCdevLibh
#define INCdevLibh 1
#include "dbDefs.h"
#include "osdVME.h"
#include "errMdef.h"
#include "shareLib.h"
#ifdef __cplusplus
extern "C" {
#endif
#ifndef EPICSDEVLIB_H
#define EPICSDEVLIB_H
/*
* epdevAddressType & EPICStovxWorksAddrType
* devLib.c must change in unison
* Support macros
*/
typedef enum {
atVMEA16,
atVMEA24,
atVMEA32,
atISA, /* memory mapped ISA access (until now only on PC) */
atVMECSR, /* VME-64 CR/CSR address space */
atLast /* atLast must be the last enum in this list */
} epicsAddressType;
/*
* pointer to an array of strings for each of
* the above address types
*/
extern const char *epicsAddressTypeName[];
epicsShareFunc long devAddressMap(void); /* print an address map */
/*
* devBusToLocalAddr()
*
* OSI routine to translate bus addresses their local CPU address mapping
*/
epicsShareFunc long devBusToLocalAddr (
epicsAddressType addrType,
size_t busAddr,
volatile void **ppLocalAddr);
/*
* devReadProbe()
*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
epicsShareFunc long devReadProbe (
unsigned wordSize, volatile const void *ptr, void *pValueRead);
/*
* devNoResponseProbe()
*
* Verifies that no devices respond at naturally aligned words
* within the specified address range. Return success if no devices
* respond. Returns an error if a device does respond or if
* a physical address for a naturally aligned word cant be mapped.
* Checks all naturally aligned word sizes between char and long for
* the entire specified range of bytes.
*/
epicsShareFunc long devNoResponseProbe(
epicsAddressType addrType,
size_t base,
size_t size
);
/*
* devWriteProbe
*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
epicsShareFunc long devWriteProbe (
unsigned wordSize, volatile void *ptr, const void *pValueWritten);
epicsShareFunc long devRegisterAddress(
const char *pOwnerName,
epicsAddressType addrType,
size_t logicalBaseAddress,
size_t size, /* bytes */
volatile void **pPhysicalAddress);
epicsShareFunc long devUnregisterAddress(
epicsAddressType addrType,
size_t logicalBaseAddress,
const char *pOwnerName);
/*
* allocate and register an unoccupied address block
*/
epicsShareFunc long devAllocAddress(
const char *pOwnerName,
epicsAddressType addrType,
size_t size,
unsigned alignment, /*n ls bits zero in addr*/
volatile void **pLocalAddress);
/*
* connect ISR to a VME interrupt vector
*/
epicsShareFunc long devConnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter);
/*
* connect ISR to an ISA interrupt level
* (not implemented)
* (API should be reviewed)
*/
epicsShareFunc long devConnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *),
void *parameter);
/*
* connect ISR to a PCI interrupt
* (not implemented)
* (API should be reviewed)
*/
epicsShareFunc long devConnectInterruptPCI(
unsigned bus,
unsigned device,
unsigned function,
void (*pFunction)(void *),
void *parameter);
/*
* disconnect ISR from a VME interrupt vector
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install
*/
epicsShareFunc long devDisconnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* disconnect ISR from an ISA interrupt level
* (not implemented)
* (API should be reviewed)
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install
*/
epicsShareFunc long devDisconnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *));
/*
* disconnect ISR from a PCI interrupt
* (not implemented)
* (API should be reviewed)
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install
*/
epicsShareFunc long devDisconnectInterruptPCI(
unsigned bus,
unsigned device,
unsigned function,
void (*pFunction)(void *));
/*
* determine if a VME interrupt vector is in use
*
* returns boolean
*/
epicsShareFunc int devInterruptInUseVME (unsigned vectorNumber);
/*
* determine if an ISA interrupt level is in use
* (not implemented)
*
* returns boolean
*/
epicsShareFunc int devInterruptLevelInUseISA (unsigned interruptLevel);
/*
* determine if a PCI interrupt is in use
* (not implemented)
*
* returns boolean
*/
epicsShareFunc int devInterruptInUsePCI (unsigned bus, unsigned device,
unsigned function);
typedef enum {intVME, intVXI, intISA} epicsInterruptType;
/*
* enable VME interrupt level
*/
epicsShareFunc long devEnableInterruptLevelVME (unsigned level);
/*
* enable ISA interrupt level
*/
epicsShareFunc long devEnableInterruptLevelISA (unsigned level);
/*
* not implemented - API needs to be reviewed
*/
epicsShareFunc long devEnableInterruptLevelPCI (unsigned level,
unsigned bus, unsigned device, unsigned function);
/*
* disable VME interrupt level
*/
epicsShareFunc long devDisableInterruptLevelVME (unsigned level);
/*
* disable ISA interrupt level
*/
epicsShareFunc long devDisableInterruptLevelISA (unsigned level);
/*
* not implemented - API needs to be reviewed
*/
epicsShareFunc long devDisableInterruptLevelPCI (unsigned level,
unsigned bus, unsigned device, unsigned function);
/*
* Routines to allocate and free memory in the A24 memory region.
*
*/
epicsShareFunc void *devLibA24Malloc(size_t);
epicsShareFunc void *devLibA24Calloc(size_t);
epicsShareFunc void devLibA24Free(void *pBlock);
/*
* Normalize a digital value and convert it to type TYPE
@@ -280,59 +55,6 @@ epicsShareFunc void devLibA24Free(void *pBlock);
*/
#define devPtrAlignTest(PTR) (!(devCreateAlignmentMask(*PTR)&(long)(PTR)))
/*
* virtual OS layer for devLib.c
*/
typedef struct devLibVirtualOS {
/*
* maps logical address to physical address, but does not detect
* two device drivers that are using the same address range
*/
long (*pDevMapAddr) (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
/*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, void *pValueRead);
/*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, const void *pValueWritten);
/*
* connect ISR to a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevConnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *), void *parameter);
/*
* disconnect ISR from a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevDisconnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *));
/*
* enable VME interrupt level
*/
long (*pDevEnableInterruptLevelVME) (unsigned level);
/*
* disable VME interrupt level
*/
long (*pDevDisableInterruptLevelVME) (unsigned level);
/* malloc/free A24 address space */
void *(*pDevA24Malloc)(size_t nbytes);
void (*pDevA24Free)(void *pBlock);
long (*pDevInit)(void);
}devLibVirtualOS;
epicsShareExtern devLibVirtualOS *pdevLibVirtualOS;
/*
* error codes (and messages) associated with devLib.c
*/
@@ -374,71 +96,12 @@ epicsShareExtern devLibVirtualOS *pdevLibVirtualOS;
#define S_dev_badCRCSR (M_devLib| 35) /*Invalid VME CR/CSR address*/
#define S_dev_vxWorksIntEnFail S_dev_intEnFail
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devConnectInterruptVME, devConnectInterruptPCI,
* devConnectInterruptISA etc. devConnectInterrupt will be removed
* in a future release.
*/
epicsShareFunc long devConnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter);
#endif /* EPICSDEVLIB_H */
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisconnectInterruptVME, devDisconnectInterruptPCI,
* devDisconnectInterruptISA etc. devDisconnectInterrupt will be removed
* in a future release.
* Retain compatibility by including VME by default
*/
epicsShareFunc long devDisconnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devEnableInterruptLevelVME, devEnableInterruptLevelPCI,
* devEnableInterruptLevelISA etc. devEnableInterruptLevel will be removed
* in a future release.
*/
epicsShareFunc long devEnableInterruptLevel(
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisableInterruptLevelVME, devDisableInterruptLevelISA,
* devDisableInterruptLevelPCI etc. devDisableInterruptLevel will be removed
* in a future release.
*/
epicsShareFunc long devDisableInterruptLevel (
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use devNoResponseProbe(). locationProbe() will be removed
* in a future release.
*/
epicsShareFunc long locationProbe (epicsAddressType addrType, char *pLocation);
/*
* Some vxWorks convenience routines
*/
void bcopyLongs(char *source, char *destination, int nlongs);
#ifdef __cplusplus
}
#ifndef NO_DEVLIB_COMPAT
# include "devLibVME.h"
#endif
#endif /* INCdevLibh.h*/

View File

@@ -1,4 +1,6 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
@@ -29,7 +31,10 @@ static const char sccsID[] = "@(#) $Id$";
#include "epicsMutex.h"
#include "errlog.h"
#include "ellLib.h"
#include "devLib.h"
#define NO_DEVLIB_COMPAT
#include "devLibVME.h"
#include "devLibVMEImpl.h"
static ELLLIST addrAlloc[atLast];
static ELLLIST addrFree[atLast];
@@ -167,7 +172,7 @@ long devBusToLocalAddr(
/*
* Call the virtual os routine to map the bus address to a CPU address
*/
status = (*pdevLibVirtualOS->pDevMapAddr) (addrType, 0, busAddr, 4, &localAddress);
status = (*pdevLibVME->pDevMapAddr) (addrType, 0, busAddr, 4, &localAddress);
if (status) {
errPrintf (status, __FILE__, __LINE__, "%s bus address =0X%X\n",
epicsAddressTypeName[addrType], (unsigned int)busAddr);
@@ -275,7 +280,7 @@ long devReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
}
}
return (*pdevLibVirtualOS->pDevReadProbe) (wordSize, ptr, pValue);
return (*pdevLibVME->pDevReadProbe) (wordSize, ptr, pValue);
}
/*
@@ -295,7 +300,7 @@ long devWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
}
}
return (*pdevLibVirtualOS->pDevWriteProbe) (wordSize, ptr, pValue);
return (*pdevLibVME->pDevWriteProbe) (wordSize, ptr, pValue);
}
/*
@@ -332,7 +337,7 @@ static long devInstallAddr (
* always map through the virtual os in case the memory
* management is set up there
*/
status = (*pdevLibVirtualOS->pDevMapAddr) (addrType, 0, base,
status = (*pdevLibVME->pDevMapAddr) (addrType, 0, base,
size, &pPhysicalAddress);
if (status) {
errPrintf (status, __FILE__, __LINE__, "%s base=0X%X size = 0X%X",
@@ -697,8 +702,8 @@ static long devLibInit (void)
if(devLibInitFlag) return(SUCCESS);
if(!pdevLibVirtualOS) {
epicsPrintf ("pdevLibVirtualOS is NULL\n");
if(!pdevLibVME) {
epicsPrintf ("pdevLibVME is NULL\n");
return S_dev_internal;
}
@@ -727,7 +732,7 @@ static long devLibInit (void)
}
epicsMutexUnlock(addrListLock);
devLibInitFlag = TRUE;
return pdevLibVirtualOS->pDevInit();
return pdevLibVME->pDevInit();
}
/*
@@ -889,7 +894,7 @@ long devNoResponseProbe (epicsAddressType addrType,
* every byte in the block must
* map to a physical address
*/
s = (*pdevLibVirtualOS->pDevMapAddr) (addrType, 0, probe, wordSize, &pPhysical);
s = (*pdevLibVME->pDevMapAddr) (addrType, 0, probe, wordSize, &pPhysical);
if (s!=SUCCESS) {
return s;
}
@@ -897,7 +902,7 @@ long devNoResponseProbe (epicsAddressType addrType,
/*
* verify that no device is present
*/
s = (*pdevLibVirtualOS->pDevReadProbe)(wordSize, pPhysical, &allWordSizes);
s = (*pdevLibVME->pDevReadProbe)(wordSize, pPhysical, &allWordSizes);
if (s==SUCCESS) {
return S_dev_addressOverlap;
}
@@ -907,6 +912,82 @@ long devNoResponseProbe (epicsAddressType addrType,
return SUCCESS;
}
long devConnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter )
{
long status;
if (!devLibInitFlag) {
status = devLibInit();
if (status) {
return status;
}
}
return (*pdevLibVME->pDevConnectInterruptVME) (vectorNumber,
pFunction, parameter);
}
long devDisconnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *) )
{
long status;
if (!devLibInitFlag) {
status = devLibInit();
if (status) {
return status;
}
}
return (*pdevLibVME->pDevDisconnectInterruptVME) (vectorNumber, pFunction);
}
int devInterruptInUseVME (unsigned level)
{
long status;
if (!devLibInitFlag) {
status = devLibInit();
if (status) {
return status;
}
}
return (*pdevLibVME->pDevInterruptInUseVME) (level);
}
long devEnableInterruptLevelVME (unsigned level)
{
long status;
if (!devLibInitFlag) {
status = devLibInit();
if (status) {
return status;
}
}
return (*pdevLibVME->pDevEnableInterruptLevelVME) (level);
}
long devDisableInterruptLevelVME (unsigned level)
{
long status;
if (!devLibInitFlag) {
status = devLibInit();
if (status) {
return status;
}
}
return (*pdevLibVME->pDevDisableInterruptLevelVME) (level);
}
/*
* devConnectInterrupt ()
*
@@ -930,7 +1011,7 @@ void *parameter)
switch(intType){
case intVME:
case intVXI:
return (*pdevLibVirtualOS->pDevConnectInterruptVME) (vectorNumber,
return (*pdevLibVME->pDevConnectInterruptVME) (vectorNumber,
pFunction, parameter);
default:
return S_dev_uknIntType;
@@ -961,7 +1042,7 @@ void (*pFunction)(void *)
switch(intType){
case intVME:
case intVXI:
return (*pdevLibVirtualOS->pDevDisconnectInterruptVME) (vectorNumber,
return (*pdevLibVME->pDevDisconnectInterruptVME) (vectorNumber,
pFunction);
default:
return S_dev_uknIntType;
@@ -989,7 +1070,7 @@ unsigned level)
switch(intType){
case intVME:
case intVXI:
return (*pdevLibVirtualOS->pDevEnableInterruptLevelVME) (level);
return (*pdevLibVME->pDevEnableInterruptLevelVME) (level);
default:
return S_dev_uknIntType;
}
@@ -1016,7 +1097,7 @@ unsigned level)
switch(intType){
case intVME:
case intVXI:
return (*pdevLibVirtualOS->pDevDisableInterruptLevelVME) (level);
return (*pdevLibVME->pDevDisableInterruptLevelVME) (level);
default:
return S_dev_uknIntType;
}
@@ -1065,7 +1146,7 @@ void *devLibA24Malloc(size_t size)
if (devLibA24Debug)
epicsPrintf ("devLibA24Malloc(%u) entered\n", (unsigned int)size);
ret = pdevLibVirtualOS->pDevA24Malloc(size);
ret = pdevLibVME->pDevA24Malloc(size);
return(ret);
}
@@ -1074,5 +1155,5 @@ void devLibA24Free(void *pBlock)
if (devLibA24Debug)
epicsPrintf("devLibA24Free(%p) entered\n", pBlock);
pdevLibVirtualOS->pDevA24Free(pBlock);
pdevLibVME->pDevA24Free(pBlock);
}

312
src/libCom/osi/devLibVME.h Normal file
View File

@@ -0,0 +1,312 @@
/*************************************************************************\
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLib.h */
/* devLib.h,v 1.1.2.8 2009/07/09 15:27:43 anj Exp */
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
*/
#ifndef INCdevLibh
#define INCdevLibh 1
#include "dbDefs.h"
#include "osdVME.h"
#include "errMdef.h"
#include "shareLib.h"
#include "devLib.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* epdevAddressType & EPICStovxWorksAddrType
* devLib.c must change in unison
*/
typedef enum {
atVMEA16,
atVMEA24,
atVMEA32,
atISA, /* memory mapped ISA access (until now only on PC) */
atVMECSR, /* VME-64 CR/CSR address space */
atLast /* atLast must be the last enum in this list */
} epicsAddressType;
/*
* pointer to an array of strings for each of
* the above address types
*/
epicsShareExtern const char *epicsAddressTypeName[];
#ifdef __cplusplus
}
#endif
/*
* To retain compatibility include everything by default
*/
#ifndef NO_DEVLIB_COMPAT
# include "devLibVMEImpl.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/*
* General API
*
* This section applies to all bus types
*/
epicsShareFunc long devAddressMap(void); /* print an address map */
/*
* devBusToLocalAddr()
*
* OSI routine to translate bus addresses their local CPU address mapping
*/
epicsShareFunc long devBusToLocalAddr (
epicsAddressType addrType,
size_t busAddr,
volatile void **ppLocalAddr);
/*
* devReadProbe()
*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
epicsShareFunc long devReadProbe (
unsigned wordSize, volatile const void *ptr, void *pValueRead);
/*
* devNoResponseProbe()
*
* Verifies that no devices respond at naturally aligned words
* within the specified address range. Return success if no devices
* respond. Returns an error if a device does respond or if
* a physical address for a naturally aligned word cant be mapped.
* Checks all naturally aligned word sizes between char and long for
* the entire specified range of bytes.
*/
epicsShareFunc long devNoResponseProbe(
epicsAddressType addrType,
size_t base,
size_t size
);
/*
* devWriteProbe
*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
epicsShareFunc long devWriteProbe (
unsigned wordSize, volatile void *ptr, const void *pValueWritten);
epicsShareFunc long devRegisterAddress(
const char *pOwnerName,
epicsAddressType addrType,
size_t logicalBaseAddress,
size_t size, /* bytes */
volatile void **pPhysicalAddress);
epicsShareFunc long devUnregisterAddress(
epicsAddressType addrType,
size_t logicalBaseAddress,
const char *pOwnerName);
/*
* allocate and register an unoccupied address block
*/
epicsShareFunc long devAllocAddress(
const char *pOwnerName,
epicsAddressType addrType,
size_t size,
unsigned alignment, /*n ls bits zero in addr*/
volatile void **pLocalAddress);
/*
* VME API
*
* Functions in this section apply only to the VME bus type
*/
/*
* connect ISR to a VME interrupt vector
*/
epicsShareFunc long devConnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter);
/*
* disconnect ISR from a VME interrupt vector
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install
*/
epicsShareFunc long devDisconnectInterruptVME(
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* determine if a VME interrupt vector is in use
*
* returns boolean
*/
epicsShareFunc int devInterruptInUseVME (unsigned vectorNumber);
/*
* enable VME interrupt level
*/
epicsShareFunc long devEnableInterruptLevelVME (unsigned level);
/*
* disable VME interrupt level
*/
epicsShareFunc long devDisableInterruptLevelVME (unsigned level);
/*
* Routines to allocate and free memory in the A24 memory region.
*
*/
epicsShareFunc void *devLibA24Malloc(size_t);
epicsShareFunc void *devLibA24Calloc(size_t);
epicsShareFunc void devLibA24Free(void *pBlock);
/*
* ISA API
*
* Functions in this section apply only to the ISA bus type
*/
/*
* connect ISR to an ISA interrupt level
* (not implemented)
* (API should be reviewed)
*/
epicsShareFunc long devConnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *),
void *parameter);
/*
* disconnect ISR from an ISA interrupt level
* (not implemented)
* (API should be reviewed)
*
* The parameter pFunction should be set to the C function pointer that
* was connected. It is used as a key to prevent a driver from inadvertently
* removing an interrupt handler that it didn't install
*/
epicsShareFunc long devDisconnectInterruptISA(
unsigned interruptLevel,
void (*pFunction)(void *));
/*
* determine if an ISA interrupt level is in use
* (not implemented)
*
* returns boolean
*/
epicsShareFunc int devInterruptLevelInUseISA (unsigned interruptLevel);
/*
* enable ISA interrupt level
*/
epicsShareFunc long devEnableInterruptLevelISA (unsigned level);
/*
* disable ISA interrupt level
*/
epicsShareFunc long devDisableInterruptLevelISA (unsigned level);
/*
* Deprecated interface
*/
#ifndef NO_DEVLIB_OLD_INTERFACE
typedef enum {intVME, intVXI, intISA} epicsInterruptType;
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devConnectInterruptVME, devConnectInterruptPCI,
* devConnectInterruptISA etc. devConnectInterrupt will be removed
* in a future release.
*/
epicsShareFunc long devConnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(void *),
void *parameter);
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisconnectInterruptVME, devDisconnectInterruptPCI,
* devDisconnectInterruptISA etc. devDisconnectInterrupt will be removed
* in a future release.
*/
epicsShareFunc long devDisconnectInterrupt(
epicsInterruptType intType,
unsigned vectorNumber,
void (*pFunction)(void *));
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devEnableInterruptLevelVME, devEnableInterruptLevelPCI,
* devEnableInterruptLevelISA etc. devEnableInterruptLevel will be removed
* in a future release.
*/
epicsShareFunc long devEnableInterruptLevel(
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use one of devDisableInterruptLevelVME, devDisableInterruptLevelISA,
* devDisableInterruptLevelPCI etc. devDisableInterruptLevel will be removed
* in a future release.
*/
epicsShareFunc long devDisableInterruptLevel (
epicsInterruptType intType, unsigned level);
/*
* NOTE: this routine has been deprecated. It exists
* for backwards compatibility purposes only.
*
* Please use devNoResponseProbe(). locationProbe() will be removed
* in a future release.
*/
epicsShareFunc long locationProbe (epicsAddressType addrType, char *pLocation);
#endif /* NO_DEVLIB_OLD_INTERFACE */
/*
* Some vxWorks convenience routines
*/
void bcopyLongs(char *source, char *destination, int nlongs);
#ifdef __cplusplus
}
#endif
#endif /* INCdevLibh.h*/

View File

@@ -0,0 +1,104 @@
/*************************************************************************\
* Copyright (c) 2010 Brookhaven Science Associates, as Operator of
* Brookhaven National Laboratory.
* Copyright (c) 2008 UChicago Argonne LLC, as Operator of Argonne
* National Laboratory.
* Copyright (c) 2002 The Regents of the University of California, as
* Operator of Los Alamos National Laboratory.
* EPICS BASE is distributed subject to a Software License Agreement found
* in file LICENSE that is included with this distribution.
\*************************************************************************/
/* devLibImpl.h */
/* */
/*
* Original Author: Marty Kraimer
* Author: Jeff Hill
* Date: 03-10-93
*/
#ifndef INCdevLibImplh
#define INCdevLibImplh 1
#include "dbDefs.h"
#include "shareLib.h"
#include "devLib.h"
#ifdef __cplusplus
extern "C" {
#endif
/*
* virtual OS layer for devLib.c
*
* The global virtual OS table pdevLibVME controls
* the behaviour of the functions defined in devLib.h.
* All of which call into the functions found in this table
* to perform system specific tasks.
*/
typedef struct devLibVME {
/*
* maps logical address to physical address, but does not detect
* two device drivers that are using the same address range
*/
long (*pDevMapAddr) (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
/*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevReadProbe) (unsigned wordSize, volatile const void *ptr, void *pValueRead);
/*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
long (*pDevWriteProbe) (unsigned wordSize, volatile void *ptr, const void *pValueWritten);
/*
* connect ISR to a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevConnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *), void *parameter);
/*
* disconnect ISR from a VME interrupt vector
* (required for backwards compatibility)
*/
long (*pDevDisconnectInterruptVME) (unsigned vectorNumber,
void (*pFunction)(void *));
/*
* enable VME interrupt level
*/
long (*pDevEnableInterruptLevelVME) (unsigned level);
/*
* disable VME interrupt level
*/
long (*pDevDisableInterruptLevelVME) (unsigned level);
/* malloc/free A24 address space */
void *(*pDevA24Malloc)(size_t nbytes);
void (*pDevA24Free)(void *pBlock);
long (*pDevInit)(void);
/*
* test if VME interrupt has an ISR connected
*/
int (*pDevInterruptInUseVME) (unsigned vectorNumber);
}devLibVME;
epicsShareExtern devLibVME *pdevLibVME;
#ifndef NO_DEVLIB_COMPAT
# define pdevLibVirtualOS pdevLibVME
#endif
#ifdef __cplusplus
}
#endif
#endif /* INCdevLibImplh */

View File

@@ -17,7 +17,7 @@
#include <epicsExit.h>
#include <rtems.h>
#include <bsp.h>
#include "devLib.h"
#include "devLibVME.h"
#include <epicsInterrupt.h>
#if defined(__PPC__) || defined(__mcf528x__)
@@ -36,7 +36,7 @@ static myISR *isrFetch(unsigned vectorNumber, void **parg);
* this routine needs to be in the symbol table
* for this code to work correctly
*/
void unsolicitedHandlerEPICS(int vectorNumber);
static void unsolicitedHandlerEPICS(int vectorNumber);
static myISR *defaultHandlerAddr[]={
(myISR*)unsolicitedHandlerEPICS,
@@ -72,42 +72,58 @@ int EPICStovxWorksAddrType[]
* maps logical address to physical address, but does not detect
* two device drivers that are using the same address range
*/
static long rtmsDevMapAddr (epicsAddressType addrType, unsigned options,
static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress);
/*
* a bus error safe "wordSize" read at the specified address which returns
* unsuccessful status if the device isnt present
*/
long rtmsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue);
static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue);
/*
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
long rtmsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue);
static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue);
static long rtemsDevConnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)(),
void *parameter);
static long rtemsDevDisconnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)()
);
static long rtemsDevEnableInterruptLevelVME (unsigned level);
static long rtemsDevDisableInterruptLevelVME (unsigned level);
static int rtemsDevInterruptInUseVME (unsigned vectorNumber);
/* RTEMS specific init */
/*devA24Malloc and devA24Free are not implemented*/
static void *devA24Malloc(size_t size) { return 0;}
static void devA24Free(void *pBlock) {};
static long rtmsDevInit(void);
static long rtemsDevInit(void);
/*
* used by bind in devLib.c
*/
static devLibVirtualOS rtemsVirtualOS = {
rtmsDevMapAddr, rtmsDevReadProbe, rtmsDevWriteProbe,
devConnectInterruptVME, devDisconnectInterruptVME,
devEnableInterruptLevelVME, devDisableInterruptLevelVME,
devA24Malloc,devA24Free,rtmsDevInit
static devLibVME rtemsVirtualOS = {
rtemsDevMapAddr, rtemsDevReadProbe, rtemsDevWriteProbe,
rtemsDevConnectInterruptVME, rtemsDevDisconnectInterruptVME,
rtemsDevEnableInterruptLevelVME, rtemsDevDisableInterruptLevelVME,
devA24Malloc,devA24Free,rtemsDevInit,rtemsDevInterruptInUseVME
};
devLibVirtualOS *pdevLibVirtualOS = &rtemsVirtualOS;
devLibVME *pdevLibVME = &rtemsVirtualOS;
/* RTEMS specific initialization */
static long
rtmsDevInit(void)
rtemsDevInit(void)
{
/* assume the vme bridge has been initialized by bsp */
/* init BSP extensions [memProbe etc.] */
@@ -119,7 +135,7 @@ rtmsDevInit(void)
*
* wrapper to minimize driver dependency on OS
*/
long devConnectInterruptVME (
static long rtemsDevConnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)(),
void *parameter)
@@ -152,7 +168,7 @@ long devConnectInterruptVME (
* an interrupt handler that was installed by another driver
*
*/
long devDisconnectInterruptVME (
static long rtemsDevDisconnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)()
)
@@ -188,7 +204,7 @@ long devDisconnectInterruptVME (
/*
* enable VME interrupt level
*/
long devEnableInterruptLevelVME (unsigned level)
static long rtemsDevEnableInterruptLevelVME (unsigned level)
{
return BSP_enableVME_int_lvl(level);
}
@@ -196,15 +212,15 @@ long devEnableInterruptLevelVME (unsigned level)
/*
* disable VME interrupt level
*/
long devDisableInterruptLevelVME (unsigned level)
static long rtemsDevDisableInterruptLevelVME (unsigned level)
{
return BSP_disableVME_int_lvl(level);
}
/*
* rtmsDevMapAddr ()
* rtemsDevMapAddr ()
*/
static long rtmsDevMapAddr (epicsAddressType addrType, unsigned options,
static long rtemsDevMapAddr (epicsAddressType addrType, unsigned options,
size_t logicalAddress, size_t size, volatile void **ppPhysicalAddress)
{
long status;
@@ -234,7 +250,7 @@ static long rtmsDevMapAddr (epicsAddressType addrType, unsigned options,
* unsuccessful status if the device isnt present
*/
rtems_status_code bspExtMemProbe(void *addr, int write, int size, void *pval);
long rtmsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
static long rtemsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue)
{
long status;
@@ -253,7 +269,7 @@ long rtmsDevReadProbe (unsigned wordSize, volatile const void *ptr, void *pValue
* a bus error safe "wordSize" write at the specified address which returns
* unsuccessful status if the device isnt present
*/
long rtmsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
static long rtemsDevWriteProbe (unsigned wordSize, volatile void *ptr, const void *pValue)
{
long status;
@@ -282,7 +298,7 @@ static myISR *isrFetch(unsigned vectorNumber, void **parg)
/*
* determine if a VME interrupt vector is in use
*/
int devInterruptInUseVME (unsigned vectorNumber)
static int rtemsDevInterruptInUseVME (unsigned vectorNumber)
{
int i;
myISR *psub;
@@ -319,7 +335,7 @@ int devInterruptInUseVME (unsigned vectorNumber)
* macro to declare handler prototypes...
*
*/
void unsolicitedHandlerEPICS(int vectorNumber)
static void unsolicitedHandlerEPICS(int vectorNumber)
{
/*
* call epicInterruptContextMessage()

View File

@@ -64,16 +64,16 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
startupInfo.wShowWindow = SW_SHOWMINNOACTIVE;
status = CreateProcess (
NULL, // pointer to name of executable module (not required if command line is specified)
(char *) pBaseExecutableName, // pointer to command line string
NULL, // pointer to process security attributes
NULL, // pointer to thread security attributes
FALSE, // handle inheritance flag
CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, // creation flags
NULL, // pointer to new environment block (defaults to caller's environement)
NULL, // pointer to current directory name (defaults to caller's current directory)
&startupInfo, // pointer to STARTUPINFO
&processInfo // pointer to PROCESS_INFORMATION
NULL, /* pointer to name of executable module (not required if command line is specified) */
(char *) pBaseExecutableName, /* pointer to command line string */
NULL, /* pointer to process security attributes */
NULL, /* pointer to thread security attributes */
FALSE, /* handle inheritance flag */
CREATE_NEW_PROCESS_GROUP | DETACHED_PROCESS, /* creation flags */
NULL, /* pointer to new environment block (defaults to caller's environement) */
NULL, /* pointer to current directory name (defaults to caller's current directory) */
&startupInfo, /* pointer to STARTUPINFO */
&processInfo /* pointer to PROCESS_INFORMATION */
);
if ( status == 0 ) {
DWORD W32status;
@@ -84,7 +84,7 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
GetLastError (),
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &errStrMsgBuf,
0,
NULL
@@ -107,24 +107,24 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
FORMAT_MESSAGE_ARGUMENT_ARRAY | 80,
"%1 \"%2\". %3 %4 %5 \"%6\"",
0,
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
MAKELANGID (LANG_NEUTRAL, SUBLANG_DEFAULT), /* Default language */
(LPTSTR) &complteMsgBuf,
0,
pFmtArgs
);
if (W32status) {
// Display the string.
/* Display the string. */
MessageBox (NULL, complteMsgBuf, "Configuration Problem",
MB_OK | MB_ICONINFORMATION);
LocalFree (complteMsgBuf);
}
else {
// Display the string.
/* Display the string. */
MessageBox (NULL, errStrMsgBuf, "Failed to start executable",
MB_OK | MB_ICONINFORMATION);
}
// Free the buffer.
/* Free the buffer. */
LocalFree (errStrMsgBuf);
}
else {
@@ -137,16 +137,17 @@ epicsShareFunc osiSpawnDetachedProcessReturn epicsShareAPI osiSpawnDetachedProce
return osiSpawnDetachedProcessSuccess;
//
// use of spawn here causes problems when the ca repeater
// inherits open files (and sockets) from the spawning
// process
//
//status = _spawnlp (_P_DETACH, pBaseExecutableName, pBaseExecutableName, NULL);
//if (status<0) {
// errlogPrintf ("!!WARNING!!\n");
// errlogPrintf ("Unable to locate the EPICS executable \"%s\".\n",
// pBaseExecutableName);
// errlogPrintf ("You may need to modify your environment.\n");
//}
/*
use of spawn here causes problems when the ca repeater
inherits open files (and sockets) from the spawning
process
status = _spawnlp (_P_DETACH, pBaseExecutableName, pBaseExecutableName, NULL);
if (status<0) {
errlogPrintf ("!!WARNING!!\n");
errlogPrintf ("Unable to locate the EPICS executable \"%s\".\n",
pBaseExecutableName);
errlogPrintf ("You may need to modify your environment.\n");
}
*/
}

View File

@@ -10,6 +10,6 @@
#include <stdlib.h>
#define epicsExportSharedSymbols
#include "devLib.h"
#include "devLibVME.h"
epicsShareDef devLibVirtualOS *pdevLibVirtualOS = NULL;
epicsShareDef devLibVME *pdevLibVME = NULL;

View File

@@ -10,8 +10,8 @@
#include <stdlib.h>
#include "devLib.h"
#include "devLibVME.h"
/* This file must contain no definitions other than the following: */
devLibVirtualOS *pdevLibVirtualOS;
devLibVME *pdevLibVME;

View File

@@ -28,7 +28,7 @@
#include <vxLib.h>
#include "epicsFindSymbol.h"
#include "devLib.h"
#include "devLibVME.h"
#include "errlog.h"
typedef void myISR (void *pParam);
@@ -52,7 +52,7 @@ static myISR *isrFetch(unsigned vectorNumber);
* this routine needs to be in the symbol table
* for this code to work correctly
*/
void unsolicitedHandlerEPICS(int vectorNumber);
static void unsolicitedHandlerEPICS(int vectorNumber);
/*
* this is in veclist.c
@@ -114,23 +114,39 @@ static void *devA24Malloc(size_t size);
static void devA24Free(void *pBlock);
static long devInit(void) { return 0;}
static long vxDevConnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)(),
void *parameter);
static long vxDevDisconnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)()
);
static long vxDevEnableInterruptLevelVME (unsigned level);
static long vxDevDisableInterruptLevelVME (unsigned level);
static int vxDevInterruptInUseVME (unsigned vectorNumber);
/*
* used by dynamic bind in devLib.c
*/
static devLibVirtualOS vxVirtualOS = {
static devLibVME vxVirtualOS = {
vxDevMapAddr, vxDevReadProbe, vxDevWriteProbe,
devConnectInterruptVME, devDisconnectInterruptVME,
devEnableInterruptLevelVME, devDisableInterruptLevelVME,
devA24Malloc,devA24Free,devInit
vxDevConnectInterruptVME, vxDevDisconnectInterruptVME,
vxDevEnableInterruptLevelVME, vxDevDisableInterruptLevelVME,
devA24Malloc,devA24Free,devInit,vxDevInterruptInUseVME
};
devLibVirtualOS *pdevLibVirtualOS = &vxVirtualOS;
devLibVME *pdevLibVME = &vxVirtualOS;
/*
* devConnectInterruptVME
*
* wrapper to minimize driver dependency on vxWorks
*/
long devConnectInterruptVME (
static long vxDevConnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)(),
void *parameter)
@@ -154,7 +170,7 @@ long devConnectInterruptVME (
/*
*
* devDisconnectInterruptVME()
* vxDevDisconnectInterruptVME()
*
* wrapper to minimize driver dependency on vxWorks
*
@@ -163,7 +179,7 @@ long devConnectInterruptVME (
* an interrupt handler that was installed by another driver
*
*/
long devDisconnectInterruptVME (
static long vxDevDisconnectInterruptVME (
unsigned vectorNumber,
void (*pFunction)()
)
@@ -198,7 +214,7 @@ long devDisconnectInterruptVME (
/*
* enable VME interrupt level
*/
long devEnableInterruptLevelVME (unsigned level)
static long vxDevEnableInterruptLevelVME (unsigned level)
{
# if CPU_FAMILY != I80X86
int s;
@@ -250,7 +266,7 @@ long devDisableInterruptLevelISA (unsigned level)
/*
* disable VME interrupt level
*/
long devDisableInterruptLevelVME (unsigned level)
static long vxDevDisableInterruptLevelVME (unsigned level)
{
# if CPU_FAMILY != I80X86
int s;
@@ -359,7 +375,7 @@ static myISR *isrFetch(unsigned vectorNumber)
/*
* determine if a VME interrupt vector is in use
*/
int devInterruptInUseVME (unsigned vectorNumber)
static int vxDevInterruptInUseVME (unsigned vectorNumber)
{
#if CPU_FAMILY == PPC
return FALSE;
@@ -397,7 +413,7 @@ int devInterruptInUseVME (unsigned vectorNumber)
* disconnected vector
*
*/
void unsolicitedHandlerEPICS(int vectorNumber)
static void unsolicitedHandlerEPICS(int vectorNumber)
{
/*
* call logMsg() and not errMessage()