Commit 898541e4 authored by tomas@poseidon.ndb.mysql.com's avatar tomas@poseidon.ndb.mysql.com

Merge tulin@bk-internal.mysql.com:/home/bk/mysql-4.1

into poseidon.ndb.mysql.com:/home/tomas/mysql-4.1
parents eeeb342b 362febbf
#!/usr/bin/perl -w
#
# cvschk -- fast offline check for new files and modifications of files
# cvschk : A perl program which checks the status of the CVS controlled
# files and gives an ASCII table sorted after the status of files.
#
# If you have used CVS, then you know that it is hard to
# get a good overview the CVS-status of the files in you
# directories. Any new files? Any files changes?
# cvschk will help the programmer get the overview in the
# situation, where we do not have access to the CVS repository.
#
# Note that the program does only local checks of the files
# If you have fast access to the CVS repositiory, then consider
# the cvsstat-program - which additionally can tell if other
# people have made newer versions of the files.
#
# The program requires Perl 5.004 (maybe previous versions also work).
#
# It is tuned to parse the output of cvs(1) version 1.9.
# Earlier and later versions may require modifications to the script.
#
# ** Note that the first line might be wrong depending **
# ** on the location of your perl program. **
#
# Sample output:
# The directory ./mytempdir is not under CVS control
#
# Changed files
# ---------------
# ./cvs2html
# ./cvschk
# ./cvsstat
#
# New files
# ---------------
# ./.#cvschk
# ./XX
# ./cvs2html.ok
#
# Deleted files
# ---------------
# (none)
# Changelog:
#
# Ver Date Author Changelog
# --- ---------- -------------------- -------------------------------------
# 1.12 2002-01-04 Michael Kohne Fixed a $foo=<> warning for
# 5.004_01 with defined($foo=<>)
# Added a --tabular|-t switch
#
# 1.11 2001-12-27 Michael Kohne Added cvsignore functionality
# Handling of 'dummy timestamp'
# Handling of 'Result of Merge'
#
# 1.10 2001-11-06 Michael Kohne Added -r and -l options
#
# 1.9 2001-08-03 Lars G. T. Jørgensen Hack to allow special entry-line
#
# 1.8 2001-06-07 Peter Toft Back to the same as 1.6
# CVS is my friend
#
# 1.7 2001-06-04 Peter Toft Peter was very tired and
# applied a wrong patch -
# version 1.7 is crap
#
# 1.6 2000-12-17 Peter Toft Better description added
#
# 1.5 2000-11-04 Peter Toft URL of cvsstat changed
#
# 1.4 2000-09-20 Peter Toft Must show deleted files also
# as the default
#
# 1.3 2000-08-08 Ole Tange and Initial version
# Peter Toft
# ---- ---------- -------------------- -------------------------------------
#
# -----------------------------------------------------------------------------
#
# This program is protected by the GPL, and all modifications of
# general interest should be emailed to the maintainer (pto@sslug.dk).
#
# This program also uses code parts from cvsstat
# (same homepage as cvschk)
#
# Copyright 2000,2001 by Peter Toft <pto@sslug.dk> and Ole Tange <ole@tange.dk>
# as well as
# Lars G. T. Jørgensen <larsj@diku.dk>
#
# The URL of the home page of cvschk is shown below.
use Time::Local;
use strict;
use Getopt::Long;
my $startdir = ".";
my $debug = 0;
my (%files,%filesok,%seen,%skip);
# Michael Kohne 12/16/01
#
# Simulation of .cvsignore as CVS does it...
#
# using .cvsignore handling makes cvschk take from 2 to 3 times
# longer to run over the same set of files.
# in my tests, disabling cvsignore altogether, cvschk takes .2
# seconds on my working directory. Adding cvsignore,takes
# .4 seconds.
# Note that I do not use individual .cvsignore files - if there
# are a lot of them in your directory tree, it will add run time
#
# variables used for .cvsignore handling
my $initcvsignoreregex;# regex holding all startup cvsignore pattersn (no ())
my $cvsignoreregex;# one regex holding all current cvsignore patterns
my $disable_cvsignore=0;# set to 1 to disable cvsignore emulation
# (available in case it's REALLY screwed up)
my $disable_ind_cvsignore=0;# set to 1 to disable finding .cvsignore files
# in each directory.
my $debug_cvsignore = 0; # For debugging .cvsignore problems
my %mon;
@mon{qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)}=
0..11; # Perl months are 0 .. 11
my ($version) = ('$Revision: 1.12 $ ' =~ /^\$\w+: (.*) \$ $/);
my $URL = "http://cvs.sslug.dk/cvs2html";
my $version_line = "cvschk version $version (see $URL)\n";
my $opt_all;
my $restrict;
my $local;
my $tabular;
my $opt_restrict;
sub show_version {print $version_line}
sub die_version {die $version_line}
sub die_usage {
my $bundled = ($] > 5.00399
? "can be bundled"
: "can't be bundled, because your Perl is too old");
die <<END_OF_USAGE; # Help in the style of GNU `ls --help' or `make --help'
Usage: $0 [OPTION]...
Show the CVS status of FILEs (the current directory by default),
traversing directories recursively and telling if new files exist
in the repository.
Options:
-a, --all Show all statistics, including the names of files that
are up to date, used tags, ignored patterns and more
-r, --restrict Don't show the names of the unknown files
(useful if you have many temporary files)
-t, --tabular Show one file per line, each preceeded with a status word,
Sorted by filename.
-l, --local Don't descend into sub-directories
-d, --debug Debug info
-h, --help Show this help end exit immediately
-V, --version Show the version line and exit immediately
The one-letter options $bundled.
END_OF_USAGE
}
sub die_help {show_version; die_usage}
# Let `-ar' mean `-a -r' and require `--all' (or -a) instead of `-all'.
if ($] > 5.00399) { # This requires 5.004, so silently skip it for older Perls.
eval {Getopt::Long::config("bundling")}; # avoid 5.003 compilation error
warn $@ if $@; # For Perl 5.004+ we do want to see any compilation error
}
GetOptions( "all|a" => \$opt_all,
"tabular|t" => \$tabular,
"restrict|r" => \$restrict,
"local|l" => \$local,
"help|h" => \&die_help,
"debug|d" => \$debug,
"version|V" => \&die_version,
) or die_usage;
sub cvs_changed_in_dir($); #define prototype (for recursion)
# functions for .cvsignore handling
# converts a given filename pattern
# (of the sort that sh(1) takes) to
# a perl regex of similar meaning.
#
# It works by doing the following:
#
# change:
# . to \.
# $ to \$
# * to .*
# ? to .
#
sub fpat_to_regex($)
{
my $fexp;
$fexp = shift;
$fexp =~ s/\./\\\./g;#change . to \.
$fexp =~ s/\$/\\\$/g;#change dollar sign to \dollar sign
$fexp =~ s/\*/.*/g;# change * to .*
$fexp =~ s/\?/./g; # change ? to .
return $fexp;
}
# copy the input list to one single regex,
# items seperated by | symbols.
# return the regex string
sub do_regex_convert
{
my $rx = "";
my $first = 1;#true for first element only
# convert each element of cvsignore into a regex
# this makes the patterns usable in perl
my $cp;
foreach $cp (@_) {
if (not $first) { $rx = $rx . "|"; }
if ($first) { $first = 0; }
$rx = $rx . fpat_to_regex($cp);
}
return $rx;
}
# first parameter is a reference to the array
# to be loaded
# the rest of the parameters are just items
# that need to be loaded into the array.
# Note that if a ! is found, the list is
# emptied, then further items are added.
# returns true if a ! was found
sub load_list_from_list
{
my $arref = shift;# get reference to array from front
my $item;
my $ret=0;#false means no ! found
chomp @_;#kill newlines
foreach $item (@_) {
$item =~ s/^\s*(.*?)\s*$/$1/;#kill leading/trailing whitespace
if ($item) { # empty string is false
push @$arref,$item;
}
if ($item eq "!") {
@$arref = ();# '!' causes list to clear
$ret = 1;# ! found
}
}
return $ret;
}
# loads the given list with lines from the
# specified file. Note that if a '!' is found
# all prior patterns are removed from the list
# before the following patterns are loaded
# first param is the filename,
# second param is a reference to an array
# that the data is to go into
# returns true if a ! was found
sub load_list_from_file
{
my @inlist;
my $fname = shift;#filename to read from
#if (not -e $fname) { return; }
my $arref = shift;#array to store into
open CVSIGNORE,"$fname" or return;#file might not exist, that's OK
@inlist = <CVSIGNORE>;
close CVSIGNORE;
return load_list_from_list($arref,@inlist);
}
# loads $cvsignoreregex from
# $initcvsignoreregex and the .cvsignore file
# in the local directory
sub load_cvsignore
{
if ($disable_ind_cvsignore) {return;}#don't look for local .cvsignore files
if ($disable_cvsignore) {return;}#don't do anything
my $dir = shift;
my @cvsignore;
# bang will be true if a ! was found. In such cases, I need
# to not use the pre-exisitng regex list.
my $bang = load_list_from_file("$dir/.cvsignore",\@cvsignore);
# if we get a local cvsignore list, then...
my $rx = do_regex_convert(@cvsignore);
if ($rx) {
$cvsignoreregex = "(";
if (not $bang) {$cvsignoreregex = $cvsignoreregex . $initcvsignoreregex . "|";}
$cvsignoreregex = $cvsignoreregex . $rx . ")";
} else {
if ($bang) {$cvsignoreregex = "";}
else {$cvsignoreregex = "(" . $initcvsignoreregex . ")";}
}
if ($debug_cvsignore) {print $dir,":",$cvsignoreregex, "\n";}
}
# loads all of the cvsignore patterns that
# can be loaded at script startup
sub load_initial_cvsignore()
{
#load the default patterns
# (taken from http://www.gnu.org/manual/cvs-1.9/html_node/cvs_141.html#IDX399)
#
# this gives you the patterns that cvs normally starts with
my @initcvsignore;
push @initcvsignore,("RCS");
push @initcvsignore,("SCCS");
push @initcvsignore,("CVS");
push @initcvsignore,("CVS.adm");
push @initcvsignore,("RCSLOG");
push @initcvsignore,("cvslog.*");
push @initcvsignore,("tags");
push @initcvsignore,("TAGS");
push @initcvsignore,(".make.state");
push @initcvsignore,(".nse_depinfo");
push @initcvsignore,("*~");
push @initcvsignore,("\#*");
push @initcvsignore,(".\#*");
push @initcvsignore,("\,*");
push @initcvsignore,("_\$\*");
push @initcvsignore,("*\$");
push @initcvsignore,("*.old");
push @initcvsignore,("*.bak");
push @initcvsignore,("*.BAK");
push @initcvsignore,("*.orig");
push @initcvsignore,("*.rej");
push @initcvsignore,(".del-*");
push @initcvsignore,("*.a");
push @initcvsignore,("*.olb");
push @initcvsignore,("*.o");
push @initcvsignore,("*.obj");
push @initcvsignore,("*.so");
push @initcvsignore,("*.exe");
push @initcvsignore,("*.Z");
push @initcvsignore,("*.elc");
push @initcvsignore,("*.ln");
push @initcvsignore,("core");
# now, load (in proper order!)
# each of the possible cvsignore files
# there are 4 possible .cvsignore files:
# $CVSROOT/CVSROOT/cvsignore
# ~/.cvsignore
# $CVSIGNORE environment variable
# .cvsignore in current directory
# The first (CVSROOT/cvsignore) would require calling cvs, so
# we won't do that one.
# The last (.cvsignore in current directory) is done
# for each directory. It's handled in the load_cvsignore routine.
# ~/.cvsignore
my @inlist;
my $item;
my $HOME=$ENV{"HOME"};
if (not $HOME) {$HOME = ".";}
load_list_from_file("$HOME/.cvsignore",\@initcvsignore);
# $CVSIGNORE environment variable
my $igstr = $ENV{"CVSIGNORE"}; # get env var
if ($igstr) {
my @iglist = split(/\s+/, $igstr); #if it exists, convert to list
load_list_from_list(\@initcvsignore,@iglist);
}
# now that @initcvsignore is setup,
# turn it into a regex string
$initcvsignoreregex = do_regex_convert(@initcvsignore);
# now preset the cvsignore regex string to match
# @initcvsignore. That way, if we aren't using local
# cvsignore files, we do nothing.
$cvsignoreregex = "(" . $initcvsignoreregex . ")";
}
# routine to see if the given name is in the cvsignore regex
# returns true if it is, false if it's not
sub ignore_file($)
{
#allow user to disable the cvsignore stuff
if ($disable_cvsignore) {return 0;}
if (not $cvsignoreregex) {return 0;}# if regex is empty, nothing matches the regex
my $filename = shift;
if ($debug_cvsignore) {print "ignore_file:",$filename,"\n";}
if ($filename =~ $cvsignoreregex) {
if ($debug_cvsignore) {print $filename," matches\n";}
return 1;
}
if ($debug_cvsignore) {print $filename," doesn't match\n";}
return 0;
}
sub cvs_changed_in_dir($) {
my $dir = shift;
my ($line,$filename,$version,$mtime,$date,
$dir_filename,$cvstime,@subdirs,
@new_in_dir,$i);
# Examine status of files in CVS/Entries
if(not open(ENTRIES,"$dir/CVS/Entries")) {
if ($tabular) {
push @{$files{Unknown}}, $dir;
}
else {
warn "The directory $dir is not under CVS control\n";
}
} else {
load_cvsignore($dir);#load up proper cvsignore for given directory
while(defined ($line=<ENTRIES>)) {
# Parse CVS/Entries-line
$line=~m!^/(.*)/(.*)/(.*)/.*/! or do {
$debug and warn("Skipping entry-line $line");
next;
};
($filename,$version,$date) = ($1,$2,$3);
$dir_filename=$dir."/".$filename;
# Mark this file as seen
$seen{$dir_filename}=1;
# if not exists: Deleted
if(not -e $dir_filename) {
push @{$files{Deleted}}, $dir_filename; next;
}
# if dir: save name for recursion
-d $dir_filename and do {
push @subdirs, $dir_filename; next;
};
# modification time of $dir_filename
$mtime= (stat $dir_filename)[9];
if($date eq "dummy timestamp") {
# dummy timestamp means it's new to the repository.
push @{$files{Changed}}, $dir_filename;
if ($debug) {
print "$dir_filename is changed\n";
}
}
elsif($date eq "Result of merge") {
# result of merge means it's changed, then updated.
push @{$files{Changed}}, $dir_filename;
if ($debug) {
print "$dir_filename is changed\n";
}
}
elsif(not
$date=~/... (...)\s+(\d+)\s+(\d+):(\d+):(\d+) (\d{4})/)
{
#bogus entry in Entires
warn "Warning: $dir_filename -> '$date' ".
"not in ctime(3) format\n";
} else {
$cvstime=timegm($5,$4,$3,$2,$mon{$1},$6);
if($cvstime != $mtime) {
push @{$files{Changed}}, $dir_filename;
if ($debug) {
print "$dir_filename is changed\n";
}
} else {
push @{$files{Unchanged}}, $dir_filename;
if ($debug) {
print "$dir_filename is Unchanged\n";
}
}
}
}
close ENTRIES;
# Locate any new files/dirs
if(not opendir(D,$dir)) {
warn("Cannot open $dir");
@new_in_dir= ();
} else {
@skip{qw(. .. CVS)}=1..3; # Filenames that that we want to ignore
#(note: these are exact filenames)
@new_in_dir=
(grep { not $seen{$_} } # files we have not already processed
map { $dir."/".$_ } # map from file to dir/file
grep { not ignore_file($_) } # ignore files in the cvsignore list
grep { not $skip{$_} } # skip files to be ignored
readdir(D));
closedir(D);
}
# Remember new files (actually non-directories)
push @{$files{New}}, grep { not -d $_ } @new_in_dir;
if ($debug) { print "@{$files{New}} are new in $dir\n"; }
# Remember new subdirs
push @subdirs, grep { -d $_ } @new_in_dir;
# Recurse all subdirs
if (not $local) {
for $i (@subdirs) { cvs_changed_in_dir($i); }
}
}
}
sub print_status()
{
my $k;
my %show_these_states = ("Changed" => 1);
if(not $restrict) {
$show_these_states{"New"} = 1;
$show_these_states{"Deleted"} = 1;
}
if($opt_all) { $show_these_states{"Unchanged"} = 1; }
if ($tabular) {
my %allfiles; # key: filesname, value: state
my ($file, $state, $statefiles);
$show_these_states{"Unknown"} = 1;
while (($state, $statefiles) = each %files) {
for my $f (@{$statefiles}) {
$allfiles{$f} = $state;
}
}
for $file (sort keys %allfiles) {
$state = $allfiles{$file};
printf("%-10s %s\n", $state, $file) if $show_these_states{$state};
}
}
else {
print "\n";
for $k (keys %show_these_states) {
if(not $files{$k} or not @{$files{$k}}) {
# no files
$files{$k}=["(none)"];
}
print("$k files\n",
"---------------\n",
map { "$_\n" } sort @{$files{$k}});
print "\n";
}
}
}
load_initial_cvsignore();
if ($debug_cvsignore) {print "initial regex:",$cvsignoreregex,"\n";}
cvs_changed_in_dir($startdir);
print_status();
.\" Copyright (c) 1999 Kungliga Tekniska Högskolan
.\" $KTH: getarg.3,v 1.1.4.1 2001/07/26 19:54:45 lha Exp $
.Dd September 24, 1999
.Dt GETARG 3
.Os ROKEN
.Sh NAME
.Nm getarg ,
.Nm arg_printusage
.Nd collect command line options
.Sh SYNOPSIS
.Fd #include <getarg.h>
.Ft int
.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind"
.Ft void
.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string"
.Sh DESCRIPTION
.Fn getarg
collects any command line options given to a program in an easily used way.
.Fn arg_printusage
pretty-prints the available options, with a short help text.
.Pp
.Fa args
is the option specification to use, and it's an array of
.Fa struct getargs
elements.
.Fa num_args
is the size of
.Fa args
(in elements).
.Fa argc
and
.Fa argv
are the argument count and argument vector to extract option from.
.Fa optind
is a pointer to an integer where the index to the last processed
argument is stored, it must be initialised to the first index (minus
one) to process (normally 0) before the first call.
.Pp
.Fa arg_printusage
take the same
.Fa args
and
.Fa num_args
as getarg;
.Fa progname is the name of the program (to be used in the help text), and
.Fa extra_string
is a string to print after the actual options to indicate more
arguments. The usefulness of this function is realised only be people
who has used programs that has help strings that doesn't match what
the code does.
.Pp
The
.Fa getargs
struct has the following elements.
.Bd -literal
struct getargs{
const char *long_name;
char short_name;
enum { arg_integer,
arg_string,
arg_flag,
arg_negative_flag,
arg_strings,
arg_double,
arg_collect
} type;
void *value;
const char *help;
const char *arg_help;
};
.Ed
.Pp
.Fa long_name
is the long name of the option, it can be
.Dv NULL ,
if you don't want a long name.
.Fa short_name
is the characted to use as short option, it can be zero. If the option
has a value the
.Fa value
field gets filled in with that value interpreted as specified by the
.Fa type
field.
.Fa help
is a longer help string for the option as a whole, if it's
.Dv NULL
the help text for the option is omitted (but it's still displayed in
the synopsis).
.Fa arg_help
is a description of the argument, if
.Dv NULL
a default value will be used, depending on the type of the option:
.Pp
.Bl -hang -width arg_negative_flag
.It arg_integer
the argument is a signed integer, and
.Fa value
should point to an
.Fa int .
.It Fa arg_string
the argument is a string, and
.Fa value
should point to a
.Fa char* .
.It Fa arg_flag
the argument is a flag, and
.Fa value
should point to a
.Fa int .
It gets filled in with either zero or one, depending on how the option
is given, the normal case beeing one. Note that if the option isn't
given, the value isn't altered, so it should be initialised to some
useful default.
.It Fa arg_negative_flag
this is the same as
.Fa arg_flag
but it reverses the meaning of the flag (a given short option clears
the flag), and the synopsis of a long option is negated.
.It Fa arg_strings
the argument can be given multiple times, and the values are collected
in an array;
.Fa value
should be a pointer to a
.Fa struct getarg_strings
structure, which holds a length and a string pointer.
.It Fa arg_double
argument is a double precision floating point value, and
.Fa value
should point to a
.Fa double .
.It Fa arg_collect
allows more fine-grained control of the option parsing process.
.Fa value
should be a pointer to a
.Fa getarg_collect_info
structure:
.Bd -literal
typedef int (*getarg_collect_func)(int short_opt,
int argc,
char **argv,
int *optind,
int *optarg,
void *data);
typedef struct getarg_collect_info {
getarg_collect_func func;
void *data;
} getarg_collect_info;
.Ed
.Pp
With the
.Fa func
member set to a function to call, and
.Fa data
to some application specific data. The parameters to the collect function are:
.Bl -inset
.It Fa short_flag
non-zero if this call is via a short option flag, zero otherwise
.It Fa argc , argv
the whole argument list
.It Fa optind
pointer to the index in argv where the flag is
.It Fa optarg
pointer to the index in argv[*optind] where the flag name starts
.It Fa data
application specific data
.El
.Pp
You can modify
.Fa *optind ,
and
.Fa *optarg ,
but to do this correct you (more or less) have to know about the inner
workings of getarg.
You can skip parts of arguments by increasing
.Fa *optarg
(you could
implement the
.Fl z Ns Ar 3
set of flags from
.Nm gzip
with this), or whole argument strings by increasing
.Fa *optind
(let's say you want a flag
.Fl c Ar x y z
to specify a coordinate); if you also have to set
.Fa *optarg
to a sane value.
.Pp
The collect function should return one of
.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG
on error, zero otherwise.
.Pp
For your convenience there is a function,
.Fn getarg_optarg ,
that returns the traditional argument string, and you pass it all
arguments, sans data, that where given to the collection function.
.Pp
Don't use this more this unless you absolutely have to.
.El
.Pp
Option parsing is similar to what
.Xr getopt
uses. Short options without arguments can be compressed
.Pf ( Fl xyz
is the same as
.Fl x y z ) ,
and short
options with arguments take these as either the rest of the
argv-string or as the next option
.Pf ( Fl o Ns Ar foo ,
or
.Fl o Ar foo ) .
.Pp
Long option names are prefixed with -- (double dash), and the value
with a = (equal),
.Fl -foo= Ns Ar bar .
Long option flags can either be specified as they are
.Pf ( Fl -help ) ,
or with an (boolean parsable) option
.Pf ( Fl -help= Ns Ar yes ,
.Fl -help= Ns Ar true ,
or similar), or they can also be negated
.Pf ( Fl -no-help
is the same as
.Fl -help= Ns no ) ,
and if you're really confused you can do it multiple times
.Pf ( Fl -no-no-help= Ns Ar false ,
or even
.Fl -no-no-help= Ns Ar maybe ) .
.Sh EXAMPLE
.Bd -literal
#include <stdio.h>
#include <string.h>
#include <getarg.h>
char *source = "Ouagadougou";
char *destination;
int weight;
int include_catalog = 1;
int help_flag;
struct getargs args[] = {
{ "source", 's', arg_string, &source,
"source of shippment", "city" },
{ "destination", 'd', arg_string, &destination,
"destination of shippment", "city" },
{ "weight", 'w', arg_integer, &weight,
"weight of shippment", "tons" },
{ "catalog", 'c', arg_negative_flag, &include_catalog,
"include product catalog" },
{ "help", 'h', arg_flag, &help_flag }
};
int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
const char *progname = "ship++";
int
main(int argc, char **argv)
{
int optind = 0;
if (getarg(args, num_args, argc, argv, &optind)) {
arg_printusage(args, num_args, progname, "stuff...");
exit (1);
}
if (help_flag) {
arg_printusage(args, num_args, progname, "stuff...");
exit (0);
}
if (destination == NULL) {
fprintf(stderr, "%s: must specify destination\n", progname);
exit(1);
}
if (strcmp(source, destination) == 0) {
fprintf(stderr, "%s: destination must be different from source\n");
exit(1);
}
/* include more stuff here ... */
exit(2);
}
.Ed
.Pp
The output help output from this program looks like this:
.Bd -literal
$ ship++ --help
Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
[--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
-s city, --source=city source of shippment
-d city, --destination=city destination of shippment
-w tons, --weight=tons weight of shippment
-c, --no-catalog include product catalog
.Ed
.Sh BUGS
It should be more flexible, so it would be possible to use other more
complicated option syntaxes, such as what
.Xr ps 1 ,
and
.Xr tar 1 ,
uses, or the AFS model where you can skip the flag names as long as
the options come in the correct order.
.Pp
Options with multiple arguments should be handled better.
.Pp
Should be integreated with SL.
.Pp
It's very confusing that the struct you pass in is called getargS.
.Sh SEE ALSO
.Xr getopt 3
%!PS-Adobe-3.0
%%Creator: groff version 1.15
%%CreationDate: Thu Nov 7 12:53:13 2002
%%DocumentNeededResources: font Times-Roman
%%+ font Times-Bold
%%+ font Courier-Bold
%%+ font Courier-Oblique
%%+ font Symbol
%%+ font Courier
%%DocumentSuppliedResources: procset grops 1.15 0
%%Pages: 4
%%PageOrder: Ascend
%%Orientation: Portrait
%%EndComments
%%BeginProlog
%%BeginResource: procset grops 1.15 0
/setpacking where{
pop
currentpacking
true setpacking
}if
/grops 120 dict dup begin
/SC 32 def
/A/show load def
/B{0 SC 3 -1 roll widthshow}bind def
/C{0 exch ashow}bind def
/D{0 exch 0 SC 5 2 roll awidthshow}bind def
/E{0 rmoveto show}bind def
/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
/G{0 rmoveto 0 exch ashow}bind def
/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
/I{0 exch rmoveto show}bind def
/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
/K{0 exch rmoveto 0 exch ashow}bind def
/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
/M{rmoveto show}bind def
/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
/O{rmoveto 0 exch ashow}bind def
/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
/Q{moveto show}bind def
/R{moveto 0 SC 3 -1 roll widthshow}bind def
/S{moveto 0 exch ashow}bind def
/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
/SF{
findfont exch
[exch dup 0 exch 0 exch neg 0 0]makefont
dup setfont
[exch/setfont cvx]cvx bind def
}bind def
/MF{
findfont
[5 2 roll
0 3 1 roll
neg 0 0]makefont
dup setfont
[exch/setfont cvx]cvx bind def
}bind def
/level0 0 def
/RES 0 def
/PL 0 def
/LS 0 def
/MANUAL{
statusdict begin/manualfeed true store end
}bind def
/PLG{
gsave newpath clippath pathbbox grestore
exch pop add exch pop
}bind def
/BP{
/level0 save def
1 setlinecap
1 setlinejoin
72 RES div dup scale
LS{
90 rotate
}{
0 PL translate
}ifelse
1 -1 scale
}bind def
/EP{
level0 restore
showpage
}bind def
/DA{
newpath arcn stroke
}bind def
/SN{
transform
.25 sub exch .25 sub exch
round .25 add exch round .25 add exch
itransform
}bind def
/DL{
SN
moveto
SN
lineto stroke
}bind def
/DC{
newpath 0 360 arc closepath
}bind def
/TM matrix def
/DE{
TM currentmatrix pop
translate scale newpath 0 0 .5 0 360 arc closepath
TM setmatrix
}bind def
/RC/rcurveto load def
/RL/rlineto load def
/ST/stroke load def
/MT/moveto load def
/CL/closepath load def
/FL{
currentgray exch setgray fill setgray
}bind def
/BL/fill load def
/LW/setlinewidth load def
/RE{
findfont
dup maxlength 1 index/FontName known not{1 add}if dict begin
{
1 index/FID ne{def}{pop pop}ifelse
}forall
/Encoding exch def
dup/FontName exch def
currentdict end definefont pop
}bind def
/DEFS 0 def
/EBEGIN{
moveto
DEFS begin
}bind def
/EEND/end load def
/CNT 0 def
/level1 0 def
/PBEGIN{
/level1 save def
translate
div 3 1 roll div exch scale
neg exch neg exch translate
0 setgray
0 setlinecap
1 setlinewidth
0 setlinejoin
10 setmiterlimit
[]0 setdash
/setstrokeadjust where{
pop
false setstrokeadjust
}if
/setoverprint where{
pop
false setoverprint
}if
newpath
/CNT countdictstack def
userdict begin
/showpage{}def
}bind def
/PEND{
clear
countdictstack CNT sub{end}repeat
level1 restore
}bind def
end def
/setpacking where{
pop
setpacking
}if
%%EndResource
%%IncludeResource: font Times-Roman
%%IncludeResource: font Times-Bold
%%IncludeResource: font Courier-Bold
%%IncludeResource: font Courier-Oblique
%%IncludeResource: font Symbol
%%IncludeResource: font Courier
grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
/Courier@0 ENC0/Courier RE/Courier-Oblique@0 ENC0/Courier-Oblique RE
/Courier-Bold@0 ENC0/Courier-Bold RE/Times-Bold@0 ENC0/Times-Bold RE
/Times-Roman@0 ENC0/Times-Roman RE
%%EndProlog
%%Page: 1 1
%%BeginPageSetup
BP
%%EndPageSetup
/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
-.834(ARG \( 3 \))-.93 F/F1 10/Times-Bold@0 SF -.2(NA)72 108 S(ME).2 E
/F2 10/Courier-Bold@0 SF(getarg)102 120 Q F0(,)A F2(arg_printusage)2.5 E
F0 2.5<ad63>2.5 G(ollect command line options)-2.5 E F1(SYNOPSIS)72 144
Q F2(#include <getarg.h>)102 156 Q/F3 10/Courier-Oblique@0 SF(int)102
186 Q F2(getarg)102 198 Q F0(\()A F3(struct getargs)A/F4 10/Symbol SF(*)
6 E F3(args)A F0(,)1.666 E F3(size_t num_args)4.166 E F0(,)1.666 E F3
(int argc)4.166 E F0(,)1.666 E F3(char)4.166 E F4(**)6 E F3(argv)A F0(,)
1.666 E F3(int)151.666 210 Q F4(*)6 E F3(optind)A F0(\);)A F3(void)102
240 Q F2(arg_printusage)102 252 Q F0(\()A F3(struct getargs)A F4(*)6 E
F3(args)A F0(,)1.666 E F3(size_t num_args)4.166 E F0(,)1.666 E F3
(const char)4.166 E F4(*)6 E F3(progname)A F0(,)1.666 E F3(const char)
151.666 264 Q F4(*)6 E F3(extra_string)A F0(\);)A F1(DESCRIPTION)72 300
Q F2(getarg)102 312 Q F0 2.721 1.666(\(\) c)D 6.053(ollects an)-1.666 F
8.553(yc)-.15 G 6.053(ommand line options gi)-8.553 F -.15(ve)-.25 G
8.552(nt).15 G 8.552(oap)-8.552 G 6.052(rogram in an easily used w)
-8.552 F(ay)-.1 E(.)-.65 E F2(arg_printusage)102 324 Q F0 -3.332 1.666
(\(\) p)D(retty-prints the a)-1.666 E -.25(va)-.2 G
(ilable options, with a short help te).25 E(xt.)-.15 E F3(args)102 342 Q
F0 .855(is the option speci\214cation to use, and it')3.355 F 3.356(sa)
-.55 G 3.356(na)-3.356 G .856(rray of)-3.356 F F3 .856(struct getargs)
3.356 F F0(elements.)3.356 E F3(num_args)5.856 E F0(is)3.356 E .344
(the size of)102 354 R F3(args)2.844 E F0 .344(\(in elements\).)2.844 F
F3(argc)5.344 E F0(and)2.844 E F3(argv)2.844 E F0 .344(are the ar)2.844
F .344(gument count and ar)-.18 F .344(gument v)-.18 F .344(ector to e)
-.15 F .343(xtract op-)-.15 F 1.127(tion from.)102 366 R F3(optind)6.127
E F0 1.127(is a pointer to an inte)3.627 F 1.127(ger where the inde)-.15
F 3.627(xt)-.15 G 3.628(ot)-3.627 G 1.128(he last processed ar)-3.628 F
1.128(gument is stored, it)-.18 F
(must be initialised to the \214rst inde)102 378 Q 2.5(x\()-.15 G
(minus one\) to process \(normally 0\) before the \214rst call.)-2.5 E
F3(arg_printusage)102 396 Q F0(tak)4.178 E 4.178(et)-.1 G 1.678(he same)
-4.178 F F3(args)4.178 E F0(and)4.178 E F3(num_args)4.178 E F0 1.678
(as getar)4.178 F(g;)-.18 E F3 1.677(progname is the name of)4.178 F
6.381(the program \(to be)102 408 R F0(progname0)12.381 E F3(0)12.381 E
F0(progname1)A F3(1)12.381 E F0(progname2)A F3(2)12.382 E F0(progname3)A
F3(3)12.382 E F0(progname4)A F3(4)102 420 Q F0(progname5)A F3
(extra_string)3.404 E F0 .904
(is a string to print after the actual options to indicate more ar)3.404
F .904(guments. The)-.18 F .025(usefulness of this function is realised\
only be people who has used programs that has help strings that doesn')
102 432 R(t)-.18 E(match what the code does.)102 444 Q(The)102 462 Q F3
(getargs)2.5 E F0(struct has the follo)2.5 E(wing elements.)-.25 E/F5 10
/Courier@0 SF(struct getargs{)102 504 Q(const char)126 516 Q F4(*)6 E F5
(long_name;)A(char short_name;)126 528 Q(enum { arg_integer,)126 540 Q
(arg_string,)165 552 Q(arg_flag,)165 564 Q(arg_negative_flag,)165 576 Q
(arg_strings,)165 588 Q(arg_double,)165 600 Q(arg_collect)168 612 Q 6
(}t)126 624 S(ype;)-6 E(void)126 636 Q F4(*)6 E F5(value;)A(const char)
126 648 Q F4(*)6 E F5(help;)A(const char)126 660 Q F4(*)6 E F5
(arg_help;)A(};)102 672 Q F3(long_name)102 690 Q F0 .207
(is the long name of the option, it can be)2.707 F F5(NULL)2.706 E F0
2.706(,i)C 2.706(fy)-2.706 G .206(ou don')-2.706 F 2.706(tw)-.18 G .206
(ant a long name.)-2.806 F F3(short_name)5.206 E F0 .397(is the charact\
ed to use as short option, it can be zero. If the option has a v)102 702
R .398(alue the)-.25 F F3(value)2.898 E F0 .398
(\214eld gets \214lled in)2.898 F -.4(RO)77 750 S 152.325(KEN September)
.4 F(24, 1999)2.5 E(1)188.865 E EP
%%Page: 2 2
%%BeginPageSetup
BP
%%EndPageSetup
/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
-.834(ARG \( 3 \))-.93 F .737(with that v)102 96 R .737
(alue interpreted as speci\214ed by the)-.25 F/F1 10/Courier-Oblique@0
SF(type)3.237 E F0(\214eld.)3.237 E F1(help)5.737 E F0 .737
(is a longer help string for the option as a)3.237 F 2.833
(whole, if it')102 108 R(s)-.55 E/F2 10/Courier@0 SF(NULL)5.333 E F0
2.833(the help te)5.333 F 2.833(xt for the option is omitted \(b)-.15 F
2.834(ut it')-.2 F 5.334(ss)-.55 G 2.834
(till displayed in the synopsis\).)-5.334 F F1(arg_help)102 120 Q F0
.391(is a description of the ar)2.891 F .391(gument, if)-.18 F F2(NULL)
2.891 E F0 2.891(ad)2.891 G(ef)-2.891 E .39(ault v)-.1 F .39
(alue will be used, depending on the type of)-.25 F(the option:)102 132
Q(ar)102 150 Q(g_inte)-.18 E 59.29(ger the)-.15 F(ar)2.5 E
(gument is a signed inte)-.18 E(ger)-.15 E 2.5(,a)-.4 G(nd)-2.5 E F1
(value)2.5 E F0(should point to an)2.5 E F1(int)2.5 E F0(.)A F1
(arg_string)102 168 Q F0(the ar)47 E(gument is a string, and)-.18 E F1
(value)2.5 E F0(should point to a)2.5 E F1(char)2.5 E/F3 10/Symbol SF(*)
A F0(.)A F1(arg_flag)102 186 Q F0 .4(the ar)59 F .4
(gument is a \215ag, and)-.18 F F1(value)2.9 E F0 .4(should point to a)
2.9 F F1(int)2.9 E F0 2.9(.I)C 2.9(tg)-2.9 G .4
(ets \214lled in with ei-)-2.9 F 1.154
(ther zero or one, depending on ho)209 198 R 3.654(wt)-.25 G 1.153
(he option is gi)-3.654 F -.15(ve)-.25 G 1.153
(n, the normal case beeing).15 F .526(one. Note that if the option isn')
209 210 R 3.026(tg)-.18 G -2.15 -.25(iv e)-3.026 H .526(n, the v).25 F
.526(alue isn')-.25 F 3.026(ta)-.18 G .527(ltered, so it should be ini-)
-3.026 F(tialised to some useful def)209 222 Q(ault.)-.1 E F1
(arg_negative_flag)102 240 Q F0 .058(this is the same as)2.558 F F1
(arg_flag)2.558 E F0 -.2(bu)2.558 G 2.558(ti).2 G 2.558(tr)-2.558 G
-2.15 -.25(ev e)-2.558 H .057(rses the meaning of the \215ag \(a gi).25
F -.15(ve)-.25 G 2.557(ns).15 G(hort)-2.557 E
(option clears the \215ag\), and the synopsis of a long option is ne)209
252 Q -.05(ga)-.15 G(ted.).05 E F1(arg_strings)102 270 Q F0 .195(the ar)
41 F .195(gument can be gi)-.18 F -.15(ve)-.25 G 2.695(nm).15 G .195
(ultiple times, and the v)-2.695 F .195
(alues are collected in an array;)-.25 F F1(value)209 282 Q F0 .947
(should be a pointer to a)3.447 F F1 .947(struct getarg_strings)3.447 F
F0 .947(structure, which)3.447 F(holds a length and a string pointer)209
294 Q(.)-.55 E F1(arg_double)102 312 Q F0(ar)47 E .538
(gument is a double precision \215oating point v)-.18 F .539(alue, and)
-.25 F F1(value)3.039 E F0 .539(should point to a)3.039 F F1(double)209
324 Q F0(.)A F1(arg_collect)102 342 Q F0(allo)41 E .345
(ws more \214ne-grained control of the option parsing process.)-.25 F F1
(value)5.344 E F0 .344(should be)2.844 F 2.5(ap)209 354 S(ointer to a)
-2.5 E F1(getarg_collect_info)2.5 E F0(structure:)2.5 E F2
(typedef int \()209 372 Q F3(*)A F2
(getarg_collect_func\)\(int short_opt,)A(int argc,)407 384 Q(char)407
396 Q F3(**)6 E F2(argv,)A(int)407 408 Q F3(*)6 E F2(optind,)A(int)407
420 Q F3(*)6 E F2(optarg,)A(void)407 432 Q F3(*)6 E F2(data\);)A
(typedef struct getarg_collect_info {)209 456 Q
(getarg_collect_func func;)233 468 Q(void)233 480 Q F3(*)6 E F2(data;)A
6(}g)209 492 S(etarg_collect_info;)-6 E F0 -.4(Wi)209 510 S 1.018
(th the).4 F F1(func)3.518 E F0 1.019
(member set to a function to call, and)3.518 F F1(data)3.519 E F0 1.019
(to some application)3.519 F
(speci\214c data. The parameters to the collect function are:)209 522 Q
F1(short_flag)209 540 Q F0
(non-zero if this call is via a short option \215ag, zero otherwise)2.5
E F1(argc)209 558 Q F0(,)A F1(argv)6 E F0(the whole ar)2.5 E
(gument list)-.18 E F1(optind)209 576 Q F0(pointer to the inde)2.5 E 2.5
(xi)-.15 G 2.5(na)-2.5 G -.18(rg)-2.5 G 2.5(vw).18 G(here the \215ag is)
-2.5 E F1(optarg)209 594 Q F0(pointer to the inde)2.5 E 2.5(xi)-.15 G
2.5(na)-2.5 G -.18(rg)-2.5 G(v[).18 E F3(*)A F0
(optind] where the \215ag name starts)A F1(data)209 612 Q F0
(application speci\214c data)2.5 E -1.1(Yo)209 630 S 3.915(uc)1.1 G
1.415(an modify)-3.915 F F3(*)3.915 E F1(optind)A F0 3.915(,a)C(nd)
-3.915 E F3(*)3.915 E F1(optarg)A F0 3.915(,b)C 1.414
(ut to do this correct you \(more or)-4.115 F(less\) ha)209 642 Q .3
-.15(ve t)-.2 H 2.5(ok).15 G(no)-2.5 E 2.5(wa)-.25 G(bout the inner w)
-2.5 E(orkings of getar)-.1 E(g.)-.18 E -1.1(Yo)209 666 S 3.604(uc)1.1 G
1.104(an skip parts of ar)-3.604 F 1.105(guments by increasing)-.18 F F3
(*)3.605 E F1(optarg)A F0 1.105(\(you could implement)3.605 F(the)209
678 Q/F4 10/Courier-Bold@0 SF<ad7a>4.567 E F1(3)A F0 .401
(set of \215ags from)2.901 F F4(gzip)2.9 E F0 .4
(with this\), or whole ar)2.9 F .4(gument strings by increas-)-.18 F
(ing)209 690 Q F3(*)3.275 E F1(optind)A F0(\(let')3.275 E 3.276(ss)-.55
G .776(ay you w)-3.276 F .776(ant a \215ag)-.1 F F4<ad63>4.942 E F1
6.776(xyz)6.776 G F0 .776(to specify a coordinate\); if)-3.5 F
(you also ha)209 702 Q .3 -.15(ve t)-.2 H 2.5(os).15 G(et)-2.5 E F3(*)
2.5 E F1(optarg)A F0(to a sane v)2.5 E(alue.)-.25 E -.4(RO)77 750 S
152.325(KEN September).4 F(24, 1999)2.5 E(2)188.865 E EP
%%Page: 3 3
%%BeginPageSetup
BP
%%EndPageSetup
/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
-.834(ARG \( 3 \))-.93 F 9.449
(The collect function should return one of)209 96 R/F1 10/Courier@0 SF
(ARG_ERR_NO_MATCH)11.948 E F0(,)A F1(ARG_ERR_BAD_ARG)209 108 Q F0(,)A F1
(ARG_ERR_NO_ARG)6 E F0(on error)2.5 E 2.5(,z)-.4 G(ero otherwise.)-2.5 E
-.15(Fo)209 126 S 4.042(ry).15 G 1.542(our con)-4.042 F -.15(ve)-.4 G
1.542(nience there is a function,).15 F/F2 10/Courier-Bold@0 SF
(getarg_optarg)4.042 E F0 1.542(\(\), that returns the)B 1.251
(traditional ar)209 138 R 1.251(gument string, and you pass it all ar)
-.18 F 1.251(guments, sans data, that where)-.18 F(gi)209 150 Q -.15(ve)
-.25 G 2.5(nt).15 G 2.5(ot)-2.5 G(he collection function.)-2.5 E(Don')
209 168 Q 2.5(tu)-.18 G(se this more this unless you absolutely ha)-2.5
E .3 -.15(ve t)-.2 H(o.).15 E .213(Option parsing is similar to what)102
186 R F1(getopt)2.713 E F0 .214(uses. Short options without ar)2.714 F
.214(guments can be compressed \()-.18 F F2(\255xyz)1.666 E F0 .207
(is the same as)102 198 R F2 1.873<ad7820ad7920ad7a>4.373 F F0 .207
(\), and short options with ar)B .207(guments tak)-.18 F 2.706(et)-.1 G
.206(hese as either the rest of the ar)-2.706 F(gv-string)-.18 E
(or as the ne)102 210 Q(xt option \()-.15 E F2<ad6f>1.666 E/F3 10
/Courier-Oblique@0 SF(foo)A F0 2.5(,o)C(r)-2.5 E F2<ad6f>4.166 E F3(foo)
6 E F0(\).)A .78(Long option names are pre\214x)102 228 R .781
(ed with -- \(double dash\), and the v)-.15 F .781
(alue with a = \(equal\),)-.25 F F2(\255-foo=)4.947 E F3(bar)A F0 3.281
(.L)C(ong)-3.281 E 3.815
(option \215ags can either be speci\214ed as the)102 240 R 6.315(ya)-.15
G 3.815(re \()-6.315 F F2(\255-help)1.666 E F0 3.815
(\), or with an \(boolean parsable\) option)B(\()102 252 Q F2
(\255-help=)1.666 E F3(yes)A F0(,)A F2(\255-help=)5.659 E F3(true)A F0
3.993(,o)C 3.993(rs)-3.993 G 1.493(imilar\), or the)-3.993 F 3.993(yc)
-.15 G 1.493(an also be ne)-3.993 F -.05(ga)-.15 G 1.493(ted \().05 F F2
(\255-no-help)1.666 E F0 1.493(is the same as)3.993 F F2(\255-help=)
103.666 264 Q F0 1.363(no\), and if you')B 1.362
(re really confused you can do it multiple times \()-.5 F F2
(\255-no-no-help=)1.666 E F3(false)A F0 3.862(,o)C(r)-3.862 E -2.15 -.25
(ev e)102 276 T(n).25 E F2(\255-no-no-help=)4.166 E F3(maybe)A F0(\).)A
/F4 10/Times-Bold@0 SF(EXAMPLE)72 300 Q F1(#include <stdio.h>)102 330 Q
(#include <string.h>)102 342 Q(#include <getarg.h>)102 354 Q(char)102
378 Q/F5 10/Symbol SF(*)6 E F1(source = "Ouagadougou";)A(char)102 390 Q
F5(*)6 E F1(destination;)A(int weight;)102 402 Q
(int include_catalog = 1;)102 414 Q(int help_flag;)102 426 Q
(struct getargs args[] = {)102 450 Q 6({")126 462 S 30(source", 's',)-6
F 6(arg_string, &source,)6 F("source of shippment", "city" },)138 474 Q
6({")126 486 S(destination", 'd', arg_string,)-6 E(&destination,)12 E
("destination of shippment", "city" },)138 498 Q 6({")126 510 S 30
(weight", 'w',)-6 F(arg_integer, &weight,)6 E
("weight of shippment", "tons" },)138 522 Q 6({")126 534 S 24
(catalog", 'c',)-6 F(arg_negative_flag, &include_catalog,)6 E
("include product catalog" },)138 546 Q 6({")126 558 S 42(help", 'h',)-6
F(arg_flag, &help_flag })6 E(};)102 570 Q
(int num_args = sizeof\(args\) / sizeof\(args[0]\); /)102 594 Q F5(*)A
F1(number of elements in args)6 E F5(*)6 E F1(/)A(const char)102 618 Q
F5(*)6 E F1(progname = "ship++";)A(int)102 642 Q(main\(int argc, char)
102 654 Q F5(**)6 E F1(argv\))A({)102 666 Q(int optind = 0;)126 678 Q
(if \(getarg\(args, num_args, argc, argv, &optind\)\) {)126 690 Q
(arg_printusage\(args, num_args, progname, "stuff..."\);)147 702 Q F0
-.4(RO)77 750 S 152.325(KEN September).4 F(24, 1999)2.5 E(3)188.865 E EP
%%Page: 4 4
%%BeginPageSetup
BP
%%EndPageSetup
/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
-.834(ARG \( 3 \))-.93 F/F1 10/Courier@0 SF(exit \(1\);)147 96 Q(})126
108 Q(if \(help_flag\) {)126 120 Q
(arg_printusage\(args, num_args, progname, "stuff..."\);)147 132 Q
(exit \(0\);)147 144 Q(})126 156 Q(if \(destination == NULL\) {)126 168
Q(fprintf\(stderr, "%s: must specify destination0, progname\);)147 180 Q
(exit\(1\);)147 192 Q(})126 204 Q
(if \(strcmp\(source, destination\) == 0\) {)126 216 Q
(fprintf\(stderr, "%s: destination must be different from source0\);)147
228 Q(exit\(1\);)147 240 Q(})126 252 Q(/)126 264 Q/F2 10/Symbol SF(*)A
F1(include more stuff here ...)6 E F2(*)6 E F1(/)A(exit\(2\);)126 276 Q
(})102 288 Q F0(The output help output from this program looks lik)102
306 Q 2.5(et)-.1 G(his:)-2.5 E F1 6($s)102 324 S(hip++ --help)-6 E
(Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city])
102 336 Q
([--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...)
120 348 Q(-s city, --source=city)102 360 Q(source of shippment)36 E
(-d city, --destination=city destination of shippment)102 372 Q
(-w tons, --weight=tons)102 384 Q(weight of shippment)36 E
(-c, --no-catalog)102 396 Q(include product catalog)72 E/F3 10
/Times-Bold@0 SF -.1(BU)72 432 S(GS).1 E F0 .9(It should be more \215e)
102 444 R .9(xible, so it w)-.15 F .901
(ould be possible to use other more complicated option syntax)-.1 F .901
(es, such as)-.15 F(what)102 456 Q F1(ps)3.167 E F0 .667(\(1\), and)B F1
(tar)3.167 E F0 .666(\(1\), uses, or the AFS model where you can skip t\
he \215ag names as long as the options)B(come in the correct order)102
468 Q(.)-.55 E(Options with multiple ar)102 486 Q
(guments should be handled better)-.18 E(.)-.55 E(Should be inte)102 504
Q(greated with SL.)-.15 E(It')102 522 Q 2.5(sv)-.55 G
(ery confusing that the struct you pass in is called getar)-2.65 E(gS.)
-.18 E F3 1.666(SEE ALSO)72 546 R F1(getopt)102 558 Q F0(\(3\))A -.4(RO)
77 750 S 152.325(KEN September).4 F(24, 1999)2.5 E(4)188.865 E EP
%%Trailer
end
%%EOF
Network Working Group R. Rivest
Request for Comments: 1321 MIT Laboratory for Computer Science
and RSA Data Security, Inc.
April 1992
The MD5 Message-Digest Algorithm
Status of this Memo
This memo provides information for the Internet community. It does
not specify an Internet standard. Distribution of this memo is
unlimited.
Acknowlegements
We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
David Chaum, and Noam Nisan for numerous helpful comments and
suggestions.
Table of Contents
1. Executive Summary 1
2. Terminology and Notation 2
3. MD5 Algorithm Description 3
4. Summary 6
5. Differences Between MD4 and MD5 6
References 7
APPENDIX A - Reference Implementation 7
Security Considerations 21
Author's Address 21
1. Executive Summary
This document describes the MD5 message-digest algorithm. The
algorithm takes as input a message of arbitrary length and produces
as output a 128-bit "fingerprint" or "message digest" of the input.
It is conjectured that it is computationally infeasible to produce
two messages having the same message digest, or to produce any
message having a given prespecified target message digest. The MD5
algorithm is intended for digital signature applications, where a
large file must be "compressed" in a secure manner before being
encrypted with a private (secret) key under a public-key cryptosystem
such as RSA.
Rivest [Page 1]
RFC 1321 MD5 Message-Digest Algorithm April 1992
The MD5 algorithm is designed to be quite fast on 32-bit machines. In
addition, the MD5 algorithm does not require any large substitution
tables; the algorithm can be coded quite compactly.
The MD5 algorithm is an extension of the MD4 message-digest algorithm
1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
design. MD5 was designed because it was felt that MD4 was perhaps
being adopted for use more quickly than justified by the existing
critical review; because MD4 was designed to be exceptionally fast,
it is "at the edge" in terms of risking successful cryptanalytic
attack. MD5 backs off a bit, giving up a little in speed for a much
greater likelihood of ultimate security. It incorporates some
suggestions made by various reviewers, and contains additional
optimizations. The MD5 algorithm is being placed in the public domain
for review and possible adoption as a standard.
For OSI-based applications, MD5's object identifier is
md5 OBJECT IDENTIFIER ::=
iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
In the X.509 type AlgorithmIdentifier [3], the parameters for MD5
should have type NULL.
2. Terminology and Notation
In this document a "word" is a 32-bit quantity and a "byte" is an
eight-bit quantity. A sequence of bits can be interpreted in a
natural manner as a sequence of bytes, where each consecutive group
of eight bits is interpreted as a byte with the high-order (most
significant) bit of each byte listed first. Similarly, a sequence of
bytes can be interpreted as a sequence of 32-bit words, where each
consecutive group of four bytes is interpreted as a word with the
low-order (least significant) byte given first.
Let x_i denote "x sub i". If the subscript is an expression, we
surround it in braces, as in x_{i+1}. Similarly, we use ^ for
superscripts (exponentiation), so that x^i denotes x to the i-th
power.
Let the symbol "+" denote addition of words (i.e., modulo-2^32
addition). Let X <<< s denote the 32-bit value obtained by circularly
shifting (rotating) X left by s bit positions. Let not(X) denote the
bit-wise complement of X, and let X v Y denote the bit-wise OR of X
and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
denote the bit-wise AND of X and Y.
Rivest [Page 2]
RFC 1321 MD5 Message-Digest Algorithm April 1992
3. MD5 Algorithm Description
We begin by supposing that we have a b-bit message as input, and that
we wish to find its message digest. Here b is an arbitrary
nonnegative integer; b may be zero, it need not be a multiple of
eight, and it may be arbitrarily large. We imagine the bits of the
message written down as follows:
m_0 m_1 ... m_{b-1}
The following five steps are performed to compute the message digest
of the message.
3.1 Step 1. Append Padding Bits
The message is "padded" (extended) so that its length (in bits) is
congruent to 448, modulo 512. That is, the message is extended so
that it is just 64 bits shy of being a multiple of 512 bits long.
Padding is always performed, even if the length of the message is
already congruent to 448, modulo 512.
Padding is performed as follows: a single "1" bit is appended to the
message, and then "0" bits are appended so that the length in bits of
the padded message becomes congruent to 448, modulo 512. In all, at
least one bit and at most 512 bits are appended.
3.2 Step 2. Append Length
A 64-bit representation of b (the length of the message before the
padding bits were added) is appended to the result of the previous
step. In the unlikely event that b is greater than 2^64, then only
the low-order 64 bits of b are used. (These bits are appended as two
32-bit words and appended low-order word first in accordance with the
previous conventions.)
At this point the resulting message (after padding with bits and with
b) has a length that is an exact multiple of 512 bits. Equivalently,
this message has a length that is an exact multiple of 16 (32-bit)
words. Let M[0 ... N-1] denote the words of the resulting message,
where N is a multiple of 16.
3.3 Step 3. Initialize MD Buffer
A four-word buffer (A,B,C,D) is used to compute the message digest.
Here each of A, B, C, D is a 32-bit register. These registers are
initialized to the following values in hexadecimal, low-order bytes
first):
Rivest [Page 3]
RFC 1321 MD5 Message-Digest Algorithm April 1992
word A: 01 23 45 67
word B: 89 ab cd ef
word C: fe dc ba 98
word D: 76 54 32 10
3.4 Step 4. Process Message in 16-Word Blocks
We first define four auxiliary functions that each take as input
three 32-bit words and produce as output one 32-bit word.
F(X,Y,Z) = XY v not(X) Z
G(X,Y,Z) = XZ v Y not(Z)
H(X,Y,Z) = X xor Y xor Z
I(X,Y,Z) = Y xor (X v not(Z))
In each bit position F acts as a conditional: if X then Y else Z.
The function F could have been defined using + instead of v since XY
and not(X)Z will never have 1's in the same bit position.) It is
interesting to note that if the bits of X, Y, and Z are independent
and unbiased, the each bit of F(X,Y,Z) will be independent and
unbiased.
The functions G, H, and I are similar to the function F, in that they
act in "bitwise parallel" to produce their output from the bits of X,
Y, and Z, in such a manner that if the corresponding bits of X, Y,
and Z are independent and unbiased, then each bit of G(X,Y,Z),
H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
the function H is the bit-wise "xor" or "parity" function of its
inputs.
This step uses a 64-element table T[1 ... 64] constructed from the
sine function. Let T[i] denote the i-th element of the table, which
is equal to the integer part of 4294967296 times abs(sin(i)), where i
is in radians. The elements of the table are given in the appendix.
Do the following:
/* Process each 16-word block. */
For i = 0 to N/16-1 do
/* Copy block i into X. */
For j = 0 to 15 do
Set X[j] to M[i*16+j].
end /* of loop on j */
/* Save A as AA, B as BB, C as CC, and D as DD. */
AA = A
BB = B
Rivest [Page 4]
RFC 1321 MD5 Message-Digest Algorithm April 1992
CC = C
DD = D
/* Round 1. */
/* Let [abcd k s i] denote the operation
a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
[ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
[ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
[ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
[ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
/* Round 2. */
/* Let [abcd k s i] denote the operation
a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
[ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
[ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
[ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
[ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
/* Round 3. */
/* Let [abcd k s t] denote the operation
a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
[ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
[ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
[ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
[ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
/* Round 4. */
/* Let [abcd k s t] denote the operation
a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
/* Do the following 16 operations. */
[ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
[ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
[ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
[ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
/* Then perform the following additions. (That is increment each
of the four registers by the value it had before this block
was started.) */
A = A + AA
B = B + BB
C = C + CC
D = D + DD
end /* of loop on i */
Rivest [Page 5]
RFC 1321 MD5 Message-Digest Algorithm April 1992
3.5 Step 5. Output
The message digest produced as output is A, B, C, D. That is, we
begin with the low-order byte of A, and end with the high-order byte
of D.
This completes the description of MD5. A reference implementation in
C is given in the appendix.
4. Summary
The MD5 message-digest algorithm is simple to implement, and provides
a "fingerprint" or message digest of a message of arbitrary length.
It is conjectured that the difficulty of coming up with two messages
having the same message digest is on the order of 2^64 operations,
and that the difficulty of coming up with any message having a given
message digest is on the order of 2^128 operations. The MD5 algorithm
has been carefully scrutinized for weaknesses. It is, however, a
relatively new algorithm and further security analysis is of course
justified, as is the case with any new proposal of this sort.
5. Differences Between MD4 and MD5
The following are the differences between MD4 and MD5:
1. A fourth round has been added.
2. Each step now has a unique additive constant.
3. The function g in round 2 was changed from (XY v XZ v YZ) to
(XZ v Y not(Z)) to make g less symmetric.
4. Each step now adds in the result of the previous step. This
promotes a faster "avalanche effect".
5. The order in which input words are accessed in rounds 2 and
3 is changed, to make these patterns less like each other.
6. The shift amounts in each round have been approximately
optimized, to yield a faster "avalanche effect." The shifts in
different rounds are distinct.
Rivest [Page 6]
RFC 1321 MD5 Message-Digest Algorithm April 1992
References
[1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and
RSA Data Security, Inc., April 1992.
[2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
Proceedings, pages 303-311, Springer-Verlag, 1991.
[3] CCITT Recommendation X.509 (1988), "The Directory -
Authentication Framework."
APPENDIX A - Reference Implementation
This appendix contains the following files taken from RSAREF: A
Cryptographic Toolkit for Privacy-Enhanced Mail:
global.h -- global header file
md5.h -- header file for MD5
md5c.c -- source code for MD5
For more information on RSAREF, send email to <rsaref@rsa.com>.
The appendix also includes the following file:
mddriver.c -- test driver for MD2, MD4 and MD5
The driver compiles for MD5 by default but can compile for MD2 or MD4
if the symbol MD is defined on the C compiler command line as 2 or 4.
The implementation is portable and should work on many different
plaforms. However, it is not difficult to optimize the implementation
on particular platforms, an exercise left to the reader. For example,
on "little-endian" platforms where the lowest-addressed byte in a 32-
bit word is the least significant and there are no alignment
restrictions, the call to Decode in MD5Transform can be replaced with
a typecast.
A.1 global.h
/* GLOBAL.H - RSAREF types and constants
*/
/* PROTOTYPES should be set to one if and only if the compiler supports
function argument prototyping.
The following makes PROTOTYPES default to 0 if it has not already
Rivest [Page 7]
RFC 1321 MD5 Message-Digest Algorithm April 1992
been defined with C compiler flags.
*/
#ifndef PROTOTYPES
#define PROTOTYPES 0
#endif
/* POINTER defines a generic pointer type */
typedef unsigned char *POINTER;
/* UINT2 defines a two byte word */
typedef unsigned short int UINT2;
/* UINT4 defines a four byte word */
typedef unsigned long int UINT4;
/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
returns an empty list.
*/
#if PROTOTYPES
#define PROTO_LIST(list) list
#else
#define PROTO_LIST(list) ()
#endif
A.2 md5.h
/* MD5.H - header file for MD5C.C
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
Rivest [Page 8]
RFC 1321 MD5 Message-Digest Algorithm April 1992
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* MD5 context. */
typedef struct {
UINT4 state[4]; /* state (ABCD) */
UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
unsigned char buffer[64]; /* input buffer */
} MD5_CTX;
void MD5Init PROTO_LIST ((MD5_CTX *));
void MD5Update PROTO_LIST
((MD5_CTX *, unsigned char *, unsigned int));
void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
A.3 md5c.c
/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
*/
/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
rights reserved.
License to copy and use this software is granted provided that it
is identified as the "RSA Data Security, Inc. MD5 Message-Digest
Algorithm" in all material mentioning or referencing this software
or this function.
License is also granted to make and use derivative works provided
that such works are identified as "derived from the RSA Data
Security, Inc. MD5 Message-Digest Algorithm" in all material
mentioning or referencing the derived work.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
#include "global.h"
#include "md5.h"
/* Constants for MD5Transform routine.
*/
Rivest [Page 9]
RFC 1321 MD5 Message-Digest Algorithm April 1992
#define S11 7
#define S12 12
#define S13 17
#define S14 22
#define S21 5
#define S22 9
#define S23 14
#define S24 20
#define S31 4
#define S32 11
#define S33 16
#define S34 23
#define S41 6
#define S42 10
#define S43 15
#define S44 21
static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
static void Encode PROTO_LIST
((unsigned char *, UINT4 *, unsigned int));
static void Decode PROTO_LIST
((UINT4 *, unsigned char *, unsigned int));
static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
static unsigned char PADDING[64] = {
0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
};
/* F, G, H and I are basic MD5 functions.
*/
#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
#define H(x, y, z) ((x) ^ (y) ^ (z))
#define I(x, y, z) ((y) ^ ((x) | (~z)))
/* ROTATE_LEFT rotates x left n bits.
*/
#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
Rotation is separate from addition to prevent recomputation.
*/
#define FF(a, b, c, d, x, s, ac) { \
(a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
Rivest [Page 10]
RFC 1321 MD5 Message-Digest Algorithm April 1992
(a) += (b); \
}
#define GG(a, b, c, d, x, s, ac) { \
(a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define HH(a, b, c, d, x, s, ac) { \
(a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
#define II(a, b, c, d, x, s, ac) { \
(a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
(a) = ROTATE_LEFT ((a), (s)); \
(a) += (b); \
}
/* MD5 initialization. Begins an MD5 operation, writing a new context.
*/
void MD5Init (context)
MD5_CTX *context; /* context */
{
context->count[0] = context->count[1] = 0;
/* Load magic initialization constants.
*/
context->state[0] = 0x67452301;
context->state[1] = 0xefcdab89;
context->state[2] = 0x98badcfe;
context->state[3] = 0x10325476;
}
/* MD5 block update operation. Continues an MD5 message-digest
operation, processing another message block, and updating the
context.
*/
void MD5Update (context, input, inputLen)
MD5_CTX *context; /* context */
unsigned char *input; /* input block */
unsigned int inputLen; /* length of input block */
{
unsigned int i, index, partLen;
/* Compute number of bytes mod 64 */
index = (unsigned int)((context->count[0] >> 3) & 0x3F);
/* Update number of bits */
if ((context->count[0] += ((UINT4)inputLen << 3))
Rivest [Page 11]
RFC 1321 MD5 Message-Digest Algorithm April 1992
< ((UINT4)inputLen << 3))
context->count[1]++;
context->count[1] += ((UINT4)inputLen >> 29);
partLen = 64 - index;
/* Transform as many times as possible.
*/
if (inputLen >= partLen) {
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)input, partLen);
MD5Transform (context->state, context->buffer);
for (i = partLen; i + 63 < inputLen; i += 64)
MD5Transform (context->state, &input[i]);
index = 0;
}
else
i = 0;
/* Buffer remaining input */
MD5_memcpy
((POINTER)&context->buffer[index], (POINTER)&input[i],
inputLen-i);
}
/* MD5 finalization. Ends an MD5 message-digest operation, writing the
the message digest and zeroizing the context.
*/
void MD5Final (digest, context)
unsigned char digest[16]; /* message digest */
MD5_CTX *context; /* context */
{
unsigned char bits[8];
unsigned int index, padLen;
/* Save number of bits */
Encode (bits, context->count, 8);
/* Pad out to 56 mod 64.
*/
index = (unsigned int)((context->count[0] >> 3) & 0x3f);
padLen = (index < 56) ? (56 - index) : (120 - index);
MD5Update (context, PADDING, padLen);
/* Append length (before padding) */
MD5Update (context, bits, 8);
Rivest [Page 12]
RFC 1321 MD5 Message-Digest Algorithm April 1992
/* Store state in digest */
Encode (digest, context->state, 16);
/* Zeroize sensitive information.
*/
MD5_memset ((POINTER)context, 0, sizeof (*context));
}
/* MD5 basic transformation. Transforms state based on block.
*/
static void MD5Transform (state, block)
UINT4 state[4];
unsigned char block[64];
{
UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
Decode (x, block, 64);
/* Round 1 */
FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
/* Round 2 */
GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
Rivest [Page 13]
RFC 1321 MD5 Message-Digest Algorithm April 1992
GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
/* Round 3 */
HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
/* Round 4 */
II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
/* Zeroize sensitive information.
Rivest [Page 14]
RFC 1321 MD5 Message-Digest Algorithm April 1992
*/
MD5_memset ((POINTER)x, 0, sizeof (x));
}
/* Encodes input (UINT4) into output (unsigned char). Assumes len is
a multiple of 4.
*/
static void Encode (output, input, len)
unsigned char *output;
UINT4 *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4) {
output[j] = (unsigned char)(input[i] & 0xff);
output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
}
}
/* Decodes input (unsigned char) into output (UINT4). Assumes len is
a multiple of 4.
*/
static void Decode (output, input, len)
UINT4 *output;
unsigned char *input;
unsigned int len;
{
unsigned int i, j;
for (i = 0, j = 0; j < len; i++, j += 4)
output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
(((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
}
/* Note: Replace "for loop" with standard memcpy if possible.
*/
static void MD5_memcpy (output, input, len)
POINTER output;
POINTER input;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
Rivest [Page 15]
RFC 1321 MD5 Message-Digest Algorithm April 1992
output[i] = input[i];
}
/* Note: Replace "for loop" with standard memset if possible.
*/
static void MD5_memset (output, value, len)
POINTER output;
int value;
unsigned int len;
{
unsigned int i;
for (i = 0; i < len; i++)
((char *)output)[i] = (char)value;
}
A.4 mddriver.c
/* MDDRIVER.C - test driver for MD2, MD4 and MD5
*/
/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
rights reserved.
RSA Data Security, Inc. makes no representations concerning either
the merchantability of this software or the suitability of this
software for any particular purpose. It is provided "as is"
without express or implied warranty of any kind.
These notices must be retained in any copies of any part of this
documentation and/or software.
*/
/* The following makes MD default to MD5 if it has not already been
defined with C compiler flags.
*/
#ifndef MD
#define MD MD5
#endif
#include <stdio.h>
#include <time.h>
#include <string.h>
#include "global.h"
#if MD == 2
#include "md2.h"
#endif
#if MD == 4
Rivest [Page 16]
RFC 1321 MD5 Message-Digest Algorithm April 1992
#include "md4.h"
#endif
#if MD == 5
#include "md5.h"
#endif
/* Length of test block, number of test blocks.
*/
#define TEST_BLOCK_LEN 1000
#define TEST_BLOCK_COUNT 1000
static void MDString PROTO_LIST ((char *));
static void MDTimeTrial PROTO_LIST ((void));
static void MDTestSuite PROTO_LIST ((void));
static void MDFile PROTO_LIST ((char *));
static void MDFilter PROTO_LIST ((void));
static void MDPrint PROTO_LIST ((unsigned char [16]));
#if MD == 2
#define MD_CTX MD2_CTX
#define MDInit MD2Init
#define MDUpdate MD2Update
#define MDFinal MD2Final
#endif
#if MD == 4
#define MD_CTX MD4_CTX
#define MDInit MD4Init
#define MDUpdate MD4Update
#define MDFinal MD4Final
#endif
#if MD == 5
#define MD_CTX MD5_CTX
#define MDInit MD5Init
#define MDUpdate MD5Update
#define MDFinal MD5Final
#endif
/* Main driver.
Arguments (may be any combination):
-sstring - digests string
-t - runs time trial
-x - runs test script
filename - digests file
(none) - digests standard input
*/
int main (argc, argv)
int argc;
Rivest [Page 17]
RFC 1321 MD5 Message-Digest Algorithm April 1992
char *argv[];
{
int i;
if (argc > 1)
for (i = 1; i < argc; i++)
if (argv[i][0] == '-' && argv[i][1] == 's')
MDString (argv[i] + 2);
else if (strcmp (argv[i], "-t") == 0)
MDTimeTrial ();
else if (strcmp (argv[i], "-x") == 0)
MDTestSuite ();
else
MDFile (argv[i]);
else
MDFilter ();
return (0);
}
/* Digests a string and prints the result.
*/
static void MDString (string)
char *string;
{
MD_CTX context;
unsigned char digest[16];
unsigned int len = strlen (string);
MDInit (&context);
MDUpdate (&context, string, len);
MDFinal (digest, &context);
printf ("MD%d (\"%s\") = ", MD, string);
MDPrint (digest);
printf ("\n");
}
/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
blocks.
*/
static void MDTimeTrial ()
{
MD_CTX context;
time_t endTime, startTime;
unsigned char block[TEST_BLOCK_LEN], digest[16];
unsigned int i;
Rivest [Page 18]
RFC 1321 MD5 Message-Digest Algorithm April 1992
printf
("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
/* Initialize block */
for (i = 0; i < TEST_BLOCK_LEN; i++)
block[i] = (unsigned char)(i & 0xff);
/* Start timer */
time (&startTime);
/* Digest blocks */
MDInit (&context);
for (i = 0; i < TEST_BLOCK_COUNT; i++)
MDUpdate (&context, block, TEST_BLOCK_LEN);
MDFinal (digest, &context);
/* Stop timer */
time (&endTime);
printf (" done\n");
printf ("Digest = ");
MDPrint (digest);
printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
printf
("Speed = %ld bytes/second\n",
(long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
}
/* Digests a reference suite of strings and prints the results.
*/
static void MDTestSuite ()
{
printf ("MD%d test suite:\n", MD);
MDString ("");
MDString ("a");
MDString ("abc");
MDString ("message digest");
MDString ("abcdefghijklmnopqrstuvwxyz");
MDString
("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
MDString
("1234567890123456789012345678901234567890\
1234567890123456789012345678901234567890");
}
/* Digests a file and prints the result.
Rivest [Page 19]
RFC 1321 MD5 Message-Digest Algorithm April 1992
*/
static void MDFile (filename)
char *filename;
{
FILE *file;
MD_CTX context;
int len;
unsigned char buffer[1024], digest[16];
if ((file = fopen (filename, "rb")) == NULL)
printf ("%s can't be opened\n", filename);
else {
MDInit (&context);
while (len = fread (buffer, 1, 1024, file))
MDUpdate (&context, buffer, len);
MDFinal (digest, &context);
fclose (file);
printf ("MD%d (%s) = ", MD, filename);
MDPrint (digest);
printf ("\n");
}
}
/* Digests the standard input and prints the result.
*/
static void MDFilter ()
{
MD_CTX context;
int len;
unsigned char buffer[16], digest[16];
MDInit (&context);
while (len = fread (buffer, 1, 16, stdin))
MDUpdate (&context, buffer, len);
MDFinal (digest, &context);
MDPrint (digest);
printf ("\n");
}
/* Prints a message digest in hexadecimal.
*/
static void MDPrint (digest)
unsigned char digest[16];
{
Rivest [Page 20]
RFC 1321 MD5 Message-Digest Algorithm April 1992
unsigned int i;
for (i = 0; i < 16; i++)
printf ("%02x", digest[i]);
}
A.5 Test suite
The MD5 test suite (driver option "-x") should print the following
results:
MD5 test suite:
MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
d174ab98d277d9f5a5611c2c9f419d9f
MD5 ("123456789012345678901234567890123456789012345678901234567890123456
78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
Security Considerations
The level of security discussed in this memo is considered to be
sufficient for implementing very high security hybrid digital-
signature schemes based on MD5 and a public-key cryptosystem.
Author's Address
Ronald L. Rivest
Massachusetts Institute of Technology
Laboratory for Computer Science
NE43-324
545 Technology Square
Cambridge, MA 02139-1986
Phone: (617) 253-5880
EMail: rivest@theory.lcs.mit.edu
Rivest [Page 21]
using System.Reflection;
using System.Runtime.CompilerServices;
//
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
//
[assembly: AssemblyTitle("")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("")]
[assembly: AssemblyCopyright("")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
//
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Revision and Build Numbers
// by using the '*' as shown below:
[assembly: AssemblyVersion("1.0.*")]
//
// In order to sign your assembly you must specify a key to use. Refer to the
// Microsoft .NET Framework documentation for more information on assembly signing.
//
// Use the attributes below to control which key is used for signing.
//
// Notes:
// (*) If no key is specified, the assembly is not signed.
// (*) KeyName refers to a key that has been installed in the Crypto Service
// Provider (CSP) on your machine. KeyFile refers to a file which contains
// a key.
// (*) If the KeyFile and the KeyName values are both specified, the
// following processing occurs:
// (1) If the KeyName can be found in the CSP, that key is used.
// (2) If the KeyName does not exist and the KeyFile does exist, the key
// in the KeyFile is installed into the CSP and used.
// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
// When specifying the KeyFile, the location of the KeyFile should be
// relative to the project output directory which is
// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
// located in the project directory, you would specify the AssemblyKeyFile
// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
// documentation for more information on this.
//
[assembly: AssemblyDelaySign(false)]
[assembly: AssemblyKeyFile("")]
[assembly: AssemblyKeyName("")]
VERSION 5.00
Begin VB.Form frmSplash
BorderStyle = 3 'Fixed Dialog
ClientHeight = 4710
ClientLeft = 45
ClientTop = 45
ClientWidth = 7455
ControlBox = 0 'False
LinkTopic = "Form1"
MaxButton = 0 'False
MinButton = 0 'False
ScaleHeight = 4710
ScaleWidth = 7455
ShowInTaskbar = 0 'False
StartUpPosition = 2 'CenterScreen
Visible = 0 'False
Begin VB.Frame fraMainFrame
Height = 4590
Left = 45
TabIndex = 0
Top = -15
Width = 7380
Begin VB.PictureBox picLogo
Height = 2385
Left = 510
Picture = "frmSplash.frx":0000
ScaleHeight = 2325
ScaleWidth = 1755
TabIndex = 2
Top = 855
Width = 1815
End
Begin VB.Label lblLicenseTo
Alignment = 1 'Right Justify
Caption = "LicenseTo"
Height = 255
Left = 270
TabIndex = 1
Tag = "LicenseTo"
Top = 300
Width = 6855
End
Begin VB.Label lblProductName
AutoSize = -1 'True
Caption = "Product"
BeginProperty Font
Name = "MS Sans Serif"
Size = 29.25
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 720
Left = 2670
TabIndex = 9
Tag = "Product"
Top = 1200
Width = 2190
End
Begin VB.Label lblCompanyProduct
AutoSize = -1 'True
Caption = "CompanyProduct"
BeginProperty Font
Name = "MS Sans Serif"
Size = 18
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 435
Left = 2505
TabIndex = 8
Tag = "CompanyProduct"
Top = 765
Width = 3000
End
Begin VB.Label lblPlatform
Alignment = 1 'Right Justify
AutoSize = -1 'True
Caption = "Platform"
BeginProperty Font
Name = "MS Sans Serif"
Size = 13.5
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 360
Left = 5865
TabIndex = 7
Tag = "Platform"
Top = 2400
Width = 1140
End
Begin VB.Label lblVersion
Alignment = 1 'Right Justify
AutoSize = -1 'True
Caption = "Version"
BeginProperty Font
Name = "MS Sans Serif"
Size = 12
Charset = 0
Weight = 700
Underline = 0 'False
Italic = 0 'False
Strikethrough = 0 'False
EndProperty
Height = 300
Left = 6075
TabIndex = 6
Tag = "Version"
Top = 2760
Width = 930
End
Begin VB.Label lblWarning
Caption = "Warning"
Height = 195
Left = 300
TabIndex = 3
Tag = "Warning"
Top = 3720
Width = 6855
End
Begin VB.Label lblCompany
Caption = "Company"
Height = 255
Left = 4710
TabIndex = 5
Tag = "Company"
Top = 3330
Width = 2415
End
Begin VB.Label lblCopyright
Caption = "Copyright"
Height = 255
Left = 4710
TabIndex = 4
Tag = "Copyright"
Top = 3120
Width = 2415
End
End
End
Attribute VB_Name = "frmSplash"
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Private Sub Form_Load()
lblVersion.Caption = "Version " & App.Major & "." & App.Minor & "." & App.Revision
lblProductName.Caption = App.Title
End Sub
/* $Id: list.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _LIST_H
#define _LIST_H
#include "sci_types.h"
typedef struct ListElement *ListElement_t;
typedef struct List *List_t;
struct ListElement {
void *element;
u_vkaddr_t key;
ListElement_t prev,next;
};
void *Get_Element(ListElement_t el);
void Set_Element(ListElement_t el,void *elptr,u_vkaddr_t key);
void Create_Element(ListElement_t *el);
void Destroy_Element(ListElement_t *el);
void Create_List(List_t *list);
void Destroy_List(List_t *list);
void Add_Element(List_t list,ListElement_t el);
void Remove_Element(List_t list,ListElement_t el);
ListElement_t Find_Element(List_t list,u_vkaddr_t key);
scibool List_Empty(List_t);
scibool List_Elements(List_t);
ListElement_t First_Element(List_t list);
ListElement_t Last_Element(List_t list);
ListElement_t Next_Element(ListElement_t el);
#endif /* _LIST_H */
/* $Id: inttypes.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SCI_OS_INTTYPES_H_
#define _SCI_OS_INTTYPES_H_
/*
* --------------------------------------------------------------------------------------
* Basic types of various sizes.
* --------------------------------------------------------------------------------------
*/
typedef unsigned char unsigned8;
typedef unsigned short unsigned16;
typedef unsigned int unsigned32;
typedef unsigned long long unsigned64;
typedef signed char signed8;
typedef signed short signed16;
typedef signed int signed32;
typedef signed long long signed64;
#ifdef CPU_WORD_IS_64_BIT
typedef unsigned64 uptr_t;
typedef signed64 iptr_t;
#else
typedef unsigned32 uptr_t;
typedef signed32 iptr_t;
#endif
#endif /* _SCI_OS_INTTYPES_H_ */
/* $Id: rmlib.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
/*********************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*********************************************************************************/
/********************************************************************************/
/* This header file contains the declarations of the SCI Reflective Memory */
/* library rmlib. The implementation of the library functions is in rmlib.c. */
/* The library contains all the functions that operate on the reflective */
/* memory. */
/* */
/* NB! */
/* */
/* DOLPHIN'S SCI REFLECTIVE MEMORY FILES ARE UNDER DEVELOPMENT AND MAY CHANGE. */
/* PLEASE CONTACT DOLPHIN FOR FURTHER INFORMATION. */
/* */
/* */
/********************************************************************************/
#include "sisci_error.h"
#include "sisci_api.h"
#include "sisci_demolib.h"
#include "sisci_types.h"
unsigned int seqerr, syncseqerr;
#ifndef _RMLIB_H
#define _RMLIB_H
#if defined(_REENTRANT)
#define _RMLIB_EXPAND_NAME(name) _RMLIB_MT_ ## name
#else
#define _RMLIB_EXPAND_NAME(name) _RMLIB_ST_ ## name
#endif
#ifdef __sparc
#define CACHE_SIZE 2097152
#else
#define CACHE_SIZE 8192
#endif
/*********************************************************************************/
/* FLAG VALUES */
/*********************************************************************************/
#define REFLECT_ERRCHECK 0x2
struct ReflectiveMemorySpace {
unsigned int localAdapterNo;
unsigned int localNodeId;
unsigned int remoteNodeId;
sci_desc_t sd;
sci_desc_t syncsd;
sci_map_t localMap;
sci_map_t remoteMap;
unsigned int localSegmentId;
unsigned int remoteSegmentId;
unsigned int syncSegmentId;
unsigned int sync_rSegmentId;
unsigned int segmentSize;
unsigned int *localMapAddr;
volatile unsigned int *remoteMapAddr;
sci_local_segment_t localSegment;
sci_remote_segment_t remoteSegment;
sci_local_segment_t syncSegment;
sci_remote_segment_t sync_rSegment;
sci_map_t syncMap;
sci_map_t sync_rMap;
sci_sequence_t syncsequence;
sci_sequence_t sequence;
unsigned int protection;
unsigned int retry_value;
sci_sequence_status_t sequenceStatus, syncsequenceStatus;
volatile unsigned int *syncMapAddr;
volatile unsigned int *sync_rMapAddr;
};
/*********************************************************************************/
/* P R I N T R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectPrintParameters _RMLIB_EXPAND_NAME(ReflectPrintParameters)
void ReflectPrintParameters(FILE *stream, struct ReflectiveMemorySpace RM_space);
/*********************************************************************************/
/* R E F L E C T D M A S E T U P */
/* */
/*********************************************************************************/
#define ReflectDmaSetup _RMLIB_EXPAND_NAME(ReflectDmaSetup)
sci_error_t ReflectDmaSetup(struct ReflectiveMemorySpace RM_space, sci_dma_queue_t *dmaQueue);
/*********************************************************************************/
/* R E F L E C T D M A R E M O V E */
/* */
/*********************************************************************************/
#define ReflectDmaRemove _RMLIB_EXPAND_NAME(ReflectDmaRemove)
sci_error_t ReflectDmaRemove(sci_dma_queue_t dmaQueue);
/*********************************************************************************/
/* R E F L E C T D M A R U N */
/* */
/*********************************************************************************/
#define ReflectDmaRun _RMLIB_EXPAND_NAME(ReflectDmaRun)
sci_error_t ReflectDmaRun(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset,
sci_dma_queue_t dmaQueue);
/*********************************************************************************/
/* C L O S E R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectClose _RMLIB_EXPAND_NAME(ReflectClose)
sci_error_t ReflectClose(struct ReflectiveMemorySpace RM_space, unsigned int segment_no);
/*********************************************************************************/
/* O P E N R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectOpen _RMLIB_EXPAND_NAME(ReflectOpen)
sci_error_t ReflectOpen(struct ReflectiveMemorySpace *RM_space,
unsigned int size,
unsigned int segment_no,
unsigned int localAdapterNo,
unsigned int remoteNodeId,
unsigned int protection,
unsigned int retry_value);
/*********************************************************************************/
/* R E F L E C T G E T A C C E S S */
/* */
/*********************************************************************************/
#define ReflectGetAccess _RMLIB_EXPAND_NAME(ReflectGetAccess)
sci_error_t ReflectGetAccess(struct ReflectiveMemorySpace *RM_space);
/*********************************************************************************/
/* R E F L E C T R E L E A S E A C C E S S */
/* */
/*********************************************************************************/
#define ReflectReleaseAccess _RMLIB_EXPAND_NAME(ReflectReleaseAccess)
sci_error_t ReflectReleaseAccess(struct ReflectiveMemorySpace *RM_space);
/*********************************************************************************/
/* R E F L E C T D M A */
/* */
/*********************************************************************************/
#define ReflectDma _RMLIB_EXPAND_NAME(ReflectDma)
sci_error_t ReflectDma(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset);
/*********************************************************************************/
/* R E F L E C T M E M C O P Y */
/* */
/*********************************************************************************/
#define ReflectMemCopy _RMLIB_EXPAND_NAME(ReflectMemCopy)
sci_error_t ReflectMemCopy(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset,
unsigned int flags);
/*********************************************************************************/
/* R E F L E C T S E T */
/* */
/*********************************************************************************/
#define ReflectSet _RMLIB_EXPAND_NAME(ReflectSet)
sci_error_t ReflectSet(struct ReflectiveMemorySpace RM_space,
unsigned int value,
unsigned int size,
unsigned int offset,
unsigned int flags
);
/*********************************************************************************/
/* R E F L E C T P R I N T */
/* */
/*********************************************************************************/
#define ReflectPrint _RMLIB_EXPAND_NAME(ReflectPrint)
sci_error_t ReflectPrint(FILE *stream,
struct ReflectiveMemorySpace RM_space,
unsigned int size,
unsigned int offset
);
#endif
/* $Id: sci_errno.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SCI_ERRNO_H_
#define _SCI_ERRNO_H_
/*
* SCI Error return values always have 30 bit set
* Remote errors should have bit 0 set
*/
#define SCI_ERR_MASK 0x40000000
#define ESCI_REMOTE_MASK 0x01000000
#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
#define _SCI_ERROR(x) ((x) | SCI_ERR_MASK)
#define _SCI_REMOTE_ERROR(x) ( _SCI_ERROR(x) | ESCI_REMOTE_MASK )
/*
* Error codes
*/
typedef enum {
ESCI_OK = 0x000,
ESCI_STILL_EXPORTED = _SCI_ERROR(0x800),
ESCI_BUS_ERR = _SCI_ERROR(0x900),
ESCI_PEND_SCIERR = _SCI_ERROR(0x901),
ESCI_SCI_ERR = _SCI_ERROR(0x902),
/*
* Specific SCI error responses:
*/
ESCI_SCI_ERR_DATA = _SCI_ERROR(0x9021),
ESCI_SCI_ERR_TYPE = _SCI_ERROR(0x9022),
ESCI_SCI_ERR_ADDR = _SCI_ERROR(0x9023),
ESCI_LINK_TIMEOUT = _SCI_ERROR(0x903),
ESCI_EXDEV_TIMEOUT = _SCI_ERROR(0x904),
ESCI_REMOTE_ERR = _SCI_ERROR(0x905),
ESCI_MBX_BUSY = _SCI_ERROR(0x906),
ESCI_DMAERR = _SCI_ERROR(0x907),
ESCI_DMA_DISABLED = _SCI_ERROR(0x908),
ESCI_SW_MBX_SEND_FAILED = _SCI_ERROR(0x909),
ESCI_HW_MBX_SEND_FAILED = _SCI_ERROR(0x90A),
ESCI_HAS_NO_SESSION = _SCI_ERROR(0xA00),
ESCI_CONNREFUSED_SESSION = _SCI_ERROR(0xA01),
ESCI_SESSION_NOT_ESTABLISHED = _SCI_ERROR(0xA11),
ESCI_REMOTE_NO_VALID_SESSION = _SCI_ERROR(0xA02),
ESCI_SESSION_DISABLED = _SCI_ERROR(0xA03),
ESCI_NODE_CLOSED = _SCI_ERROR(0xA04),
ESCI_NODE_DISABLED = _SCI_ERROR(0xA05),
ESCI_LOCAL_MASTER_ERR = _SCI_ERROR(0xA06),
ESCI_REMOTE_MASTER_ERR = _SCI_REMOTE_ERROR(0xA06),
ESCI_ILLEGAL_CMD_RECEIVED = _SCI_ERROR(0xA08),
ESCI_ILLEGAL_CMD_SENT = _SCI_ERROR(0xA09),
/* used above: ESCI_SESSION_NOT_ESTABLISHED = _SCI_ERROR(0xA11), */
/*
* Remote error codes
*/
ESCI_CONNREFUSED = _SCI_ERROR(0xB00),
ESCI_NODE_NOT_RESPONDING = _SCI_ERROR(0xB01),
ESCI_ISCONN = _SCI_ERROR(0xB02),
ESCI_HOSTUNREACH = _SCI_ERROR(0xB03),
ESCI_NO_SUCH_USER_ID = _SCI_ERROR(0xB04),
ESCI_REMOTE_NO_SUCH_USER_ID = _SCI_REMOTE_ERROR(0xB04), /* ESCI_NO_SUCH_USER_ID */
ESCI_NO_SUCH_KEY = _SCI_ERROR(0xB04), /* ESCI_NO_SUCH_USER_ID */
ESCI_REMOTE_NO_SUCH_KEY = _SCI_REMOTE_ERROR(0xB04), /* ESCI_REMOTE_NO_SUCH_USER_ID */
ESCI_NODE_ERR = _SCI_ERROR(0xB06),
ESCI_REMOTE_NODE_ERR = _SCI_REMOTE_ERROR(0xB06), /* ESCI_NODE_ERR */
ESCI_NOSPC = _SCI_ERROR(0xB08),
ESCI_REMOTE_NOSPC = _SCI_REMOTE_ERROR(0xB08), /* ESCI_NOSPC */
ESCI_NODMASPC = _SCI_ERROR(0xB0A),
ESCI_REMOTE_NODMASPC = _SCI_REMOTE_ERROR(0xB0A), /* ESCI_NODMASPC */
ESCI_NOTMAP = _SCI_ERROR(0xC00),
ESCI_ISMAP = _SCI_ERROR(0xC01),
ESCI_NOT_INITIALIZED = _SCI_ERROR(0xD00),
ESCI_REMOTE_NOT_INITIALIZED = _SCI_REMOTE_ERROR(ESCI_NOT_INITIALIZED),
/*
* ???
*/
ESCI_PARAM_ERR = _SCI_ERROR(0xD01),
ESCI_NO_FREE_VC = _SCI_ERROR(0xD02),
ESCI_REMOTE_NO_FREE_VC = _SCI_REMOTE_ERROR(0xD02), /* ESCI_NO_FREE_VC */
/*
* Adapter state related error codes:
*/
ESCI_SUSPENDED = _SCI_ERROR(0xD03),
ESCI_NOT_SUSPENDED = _SCI_ERROR(0xD04),
ESCI_NOT_READY = _SCI_ERROR(0xD05),
ESCI_NOT_CONFIGURED = _SCI_ERROR(0xD06),
ESCI_INVALID_ADAPTERID = _SCI_ERROR(0xD07), /* if an adapter-id is out of range */
ESCI_NONEXIST_ADAPTERID = _SCI_ERROR(0xD08), /* if adapter-id is valid but no adapter matches */
ESCI_ADAPTERID_INUSE = _SCI_ERROR(0xD09),
ESCI_INVALID_INSTANCE = _SCI_ERROR(0xD0A),
ESCI_NONEXIST_INSTANCE = _SCI_ERROR(0xD0B),
ESCI_ADAPTER_INIT_FAILURE = _SCI_ERROR(0xD0C),
ESCI_PAUSED = _SCI_ERROR(0xD0D),
ESCI_NOT_PAUSED = _SCI_ERROR(0xD0E),
ESCI_ADAPTER_NEED_RESET = _SCI_ERROR(0xD0F),
ESCI_NONEXIST_SERIAL_NUMBER = _SCI_ERROR(0xD10),
ESCI_NOT_AVAILABLE = _SCI_ERROR(0xD11),
ESCI_EACCESS = _SCI_ERROR(0xD12),
/*
* Local error codes
*/
ESCI_NO_LOCAL_ACCESS = _SCI_ERROR(0xE00),
ESCI_LRESOURCE_BUSY = _SCI_ERROR(0xE01),
ESCI_LRESOURCE_EXIST = _SCI_ERROR(0xE02),
ESCI_NO_LRESOURCE = _SCI_ERROR(0xE03),
ESCI_NOTCONN = _SCI_ERROR(0xE04),
ESCI_LOCAL_ERR = _SCI_ERROR(0xE05),
ESCI_NOVAL_NODEID = _SCI_ERROR(0xE06),
ESCI_NOT_SUPPORTED = _SCI_ERROR(0xE07),
ESCI_TIMEOUT = _SCI_ERROR(0xE08),
ESCI_NO_LOCAL_LC_ACCESS = _SCI_ERROR(0xE0A),
ESCI_INVALID_ATT = _SCI_ERROR(0xE0B),
ESCI_BAD_CHECKSUM = _SCI_ERROR(0xE0C),
ESCI_INTERRUPT_FLAG_DISABLED = _SCI_ERROR(0xE0D),
ESCI_COND_INT_RACE_PROBLEM = _SCI_ERROR(0xE0E),
ESCI_OVERFLOW = _SCI_ERROR(0xE0F),
ESCI_BLINK_PARITY_ERROR = _SCI_ERROR(0xE10),
ESCI_FIRMWARE_VERSION_MISMATCH = _SCI_ERROR(0xE11),
/*
* Link error codes
*/
ESCI_NO_LINK_ACCESS = _SCI_ERROR(0xF00),
ESCI_NO_REMOTE_LINK_ACCESS = _SCI_REMOTE_ERROR(0xF00), /* ESCI_NO_LINK_ACCESS */
ESCI_NO_SUCH_NODE = _SCI_ERROR(0xF02),
ESCI_USR_ACCESS_DISABLED = _SCI_ERROR(0xF03),
ESCI_HW_AVOID_DEADLOCK = _SCI_ERROR(0xF04),
ESCI_POTENTIAL_ERROR = _SCI_ERROR(0xF05),
ESCI_FENCED = _SCI_ERROR(0xF06),
ESCI_SWITCH_HW_FAILURE = _SCI_ERROR(0xF07),
ESCI_SWITCH_WRONG_BLINK_ID = _SCI_ERROR(0xF08),
ESCI_SWITCH_WRONG_PORT_NUMB = _SCI_ERROR(0xF09),
ESCI_SWITCH_WRONG_INIT_TYPE = _SCI_ERROR(0xF0A), /* It is determined that the swith initialization
* do not match the local adapter initialization
*/
ESCI_SWITCH_WRONG_SWITCH_NUMB = _SCI_ERROR(0xF0B), /* It is determined that we are operationg on the
* wrong switch port
*/
ESCI_SWITCH_NOT_CONNECTED = _SCI_ERROR(0xF0C),
ESCI_SWITCH_NOT_RECOGNIZED = _SCI_ERROR(0xF0D),
ESCI_SWITCH_INIT_IN_PROGRESS = _SCI_ERROR(0xF0E), /* Switch TINI initialization in progress */
ESCI_NO_BACKBONE_LINK_ACCESS = _SCI_ERROR(0xF20),
ESCI_BACKBONE_FENCED = _SCI_ERROR(0xF21),
ESCI_NO_BACKBONE_ACCESS = _SCI_ERROR(0xF22),
ESCI_BACKBONE_CABLE_PROBLEM = _SCI_ERROR(0xF23),
ESCI_BACKBONE_BLINK_PROBLEM = _SCI_ERROR(0xF24),
ESCI_BACKBONE_HWINIT_PROBLEM = _SCI_ERROR(0xF25),
ESCI_BACKBONE_ID_PROBLEM = _SCI_ERROR(0xF26),
ESCI_BACKBONE_STATE_PROBLEM = _SCI_ERROR(0xF27),
ESCI_BACKBONE_REQ_LINK_PROBLEM = _SCI_ERROR(0xF28),
ESCI_BACKBONE_UNFENCING = _SCI_ERROR(0xF29), /* Unfencing in progress */
/*
* added for pci port
*/
ESCI_AGAIN = _SCI_ERROR(0xF15),
ESCI_ORANGE = _SCI_ERROR(0xF16), /* Out of range */
ESCI_NOSYS = _SCI_ERROR(0xF17), /* Used instead of ENOSYS. Means function not implemented */
ESCI_REMOTE_NOSYS = _SCI_REMOTE_ERROR(ESCI_NOSYS),
ESCI_INTR = _SCI_ERROR(0xF18), /* Used instead of EINTR from sys/errno.h */
ESCI_IO = _SCI_ERROR(0xF19), /* Used instead of EIO from sys/errno.h */
ESCI_FAULT = _SCI_ERROR(0xF1A), /* Used instead of EFAULT from sys/errno.h */
ESCI_BUSY = _SCI_ERROR(0xF1B), /* Used instead of EBUST from sys/errno.h */
ESCI_INVAL = _SCI_ERROR(0xF1C), /* Used instead of EINVAL from sys/errno.h */
ESCI_NXIO = _SCI_ERROR(0xF1D), /* Used instead of ENXIO from sys/errno.h */
ESCI_EXIST = _SCI_ERROR(0xF1E) /* Used instead of EEXIST from sys/errno.h */
} scierror_t;
#endif /* _SCI_ERRNO_H_ */
/* $Id: sci_types.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SCI_TYPES_H_
#define _SCI_TYPES_H_
/*
* Remains for the time being for backward compatibility ....
*/
/* #define UNIQUE(type) struct { type x; } * */
#ifndef UNIQUE
#define UNIQUE(type) type
#endif
#include "os/inttypes.h"
#if defined(WIN32)
#if defined(_KERNEL)
#include <ntddk.h>
#else
#include <WTYPES.H>
#endif /* _KERNEL */
#else
#if defined(Linux)
#if defined(__KERNEL__)
#include <linux/types.h>
#else
#include <sys/types.h>
#endif
#else
#include <sys/types.h>
#endif
#ifdef SUNOS5
#include <sys/ddi.h>
#include <sys/sunddi.h>
#endif
#ifdef OS_IS_TRU64
#include <io/common/devdriver.h>
#endif
#ifdef OS_IS_HP_UX11
#if defined(_KERNEL)
#include <../wsio/wsio.h>
#else
#include <sys/wsio.h>
#endif
#endif
#endif
/* See comments about "UNCONFIGURED_ADAPTERS" in config.h */
#define UNCONFIGURED_ADAPTERS 100
#ifndef FALSE
#define FALSE 0
#endif
#ifndef TRUE
#define TRUE 1
#endif
#ifndef NULL
#define NULL 0
#endif
#ifndef IN
#define IN
#endif
#ifndef NOT
#define NOT !
#endif
/*
* --------------------------------------------------------------------------------------
* Basic types of various sizes.
* --------------------------------------------------------------------------------------
*/
typedef signed32 scibool;
#ifndef OS_IS_VXWORKS
typedef signed32 BOOL;
#else
/* VXWORKS has already defined BOOL */
#endif
typedef unsigned32 node_t; /* This is the logical nodeid */
typedef unsigned32 sciNodeId_t; /* This is the physical 16 bit SCI nodeid */
/*
* --------------------------------------------------------------------------------------
* Various register types.
* --------------------------------------------------------------------------------------
*/
typedef volatile unsigned32 register32;
/*
Temporary for Windows NT, until we use only the above types.
*/
#ifdef WIN32
typedef unsigned char u_char;
typedef unsigned short u_short;
typedef unsigned long u_long;
typedef unsigned int u_int;
typedef char * caddr_t;
typedef long off_t;
typedef unsigned int size_t;
#endif
#ifdef OS_IS_VXWORKS
#include <vxWorks.h>
#endif
/*
* --------------------------------------------------------------------------------------
* Various address types.
*
* We are using a struct * instead of unsigned long (int) inorder to enforce strong
* type checking
*
* --------------------------------------------------------------------------------------
*/
typedef UNIQUE(void *) vkaddr_t; /* Virtual kernel address */
typedef UNIQUE(uptr_t) vuaddr_t; /* Virtual user address */
typedef UNIQUE(unsigned32) remaddr_t; /* Remote IO address (physical address on PCs) */
typedef UNIQUE(unsigned32) sciofs_lo_t; /* Lower 32 bits of an SCI offset. */
typedef UNIQUE(unsigned32) sciofs_hi_t; /* The upper 16 bits of an SCI offset. */
typedef UNIQUE(unsigned32) ioaddr_t; /* Local IO address (physical address on PCs) */
typedef unsigned32 u_ioaddr_t;
typedef unsigned32 iooffset_t;
typedef unsigned32 iosize_t;
typedef uptr_t vkoffset_t;
typedef uptr_t u_vkaddr_t;
typedef uptr_t u_vuaddr_t;
typedef unsigned32 u_sciofs_lo_t;
typedef unsigned32 u_sciofs_hi_t;
typedef unsigned32 u_remaddr_t;
typedef unsigned32 attOffset_t; /* Address displacement from start of ATT entry */
typedef unsigned32 adapterNo_t;
typedef enum {
NO_NODE = 0,
AD_MEM_NODE = 1,
AD_ALT_NODE = 2,
AD_MBX_NODE = 3,
AD_LC_NODE = 4,
AD_LC_PORT_0 = 5,
AD_LC_PORT_1 = 6,
AD_LC_PORT_2 = 7,
PHYS_NODE = 8
} node_type_t;
/*
* Currently we don't support more than 32 bit sizes.
*/
#define SIZEOF(x) ((unsigned32)sizeof(x))
#if defined(_KERNEL)
/*
* --------------------------------------------------------------------------------------
* Some small macros intended to ease the transition to more strongly typed address
* types. The intention is that they in the long run shall be removed ...
* --------------------------------------------------------------------------------------
*/
#define P2SIZE_T(x) ((size_t)((uptr_t)(x))) /* Pointer to size_t */
#define P2U32(x) ((unsigned32)((uptr_t)(x))) /* Pointer to Unsigned 32-bit int */
#ifdef WIN32
#define PHADDR(x) ((ioaddr_t)(x))
#define HASV(x) (x)
#endif
#if 0
static vkaddr_t VKPTR (void * ptr) { return (vkaddr_t)ptr; }
static vkaddr_t VKADDR(volatile void * ptr) { return (vkaddr_t)ptr; }
#else
#define VKPTR(ptr) (vkaddr_t)ptr
#define VKADDR(ptr) (vkaddr_t)ptr
#endif
#ifdef KLOG
#define KLOG_LOG(n,m,v) ts_log((n),(m),(v))
#else
#define KLOG_LOG(n,m,v)
#endif /* KLOG */
/*
* --------------------------------------------------------------------------------------
*
* M E M A R E A T
*
* Memory area descriptor.
*
* paddr -- Physical address (aligned) of memory area
* ual_vaddr -- (Kernel )Virtual address of the unaligned memory area
* vaddr -- (Kernel) Virtual address of memory area
* rsize -- Real (Physical) Size of memory area
* msize -- Mapped (Virtual) Size of memory area (Size of area mapped
* into virtual) memory
*
* --------------------------------------
* | | <----- msize ----->| |
* |<------|------- rsize ------|------>|
* --------------------------------------
* /|\ /|\
* | |
* ual_vaddr vaddr/paddr
*
* --------------------------------------------------------------------------------------
*/
struct _memarea_ {
ioaddr_t ioaddr;
vkaddr_t vaddr;
vkaddr_t ual_vaddr;
size_t rsize;
size_t msize;
char *id;
unsigned32 cookie;
#ifdef SUNOS5
#ifdef _USE_NEW_SOLARIS_DDI_INTERFACE
ddi_acc_handle_t mem_handle;
ddi_dma_handle_t dma_handle;
#else
ddi_dma_handle_t handle;
#endif
#endif
#ifdef OS_IS_TRU64
dma_handle_t dma_handle;
#endif
#if OS_IS_LINUX
unsigned long ph_base_addr;
#endif
#ifdef OS_IS_HP_UX11
struct isc_table_type * isc;
wsio_shmem_attr_t type;
#endif
};
typedef struct _memarea_ memarea_t;
#ifdef SCI_MALLOC_DEBUG
struct _maddr_ {
char *id;
size_t size;
struct _maddr_ *next;
struct _maddr_ **prev;
unsigned32 cookie;
};
typedef struct _maddr_ maddr_t;
#define MALLOC_COOKIE 0xc3c3c3c3
#else
typedef struct { void *p; } *maddr_t;
#endif /* SCI_MALLOC_DEBUG */
typedef struct {
scibool disabled;
unsigned32 disable_cnt;
} disable_info_t;
#endif /* _KERNEL */
#endif /* _SCI_TYPES_H_ */
This source diff could not be displayed because it is too large. You can view the blob instead.
/* $Id: sisci_demolib.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_DEMOLIB_H
#define _SISCI_DEMOLIB_H
#if defined(_REENTRANT)
#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_MT_ ## name
#else
#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_ST_ ## name
#endif
/*********************************************************************************/
/* Q U E R Y A D A P T E R */
/* */
/*********************************************************************************/
#define QueryAdapter _SISCI_DEMOLIB_EXPAND_NAME(QueryAdapter)
sci_error_t QueryAdapter(
unsigned int subcommand,
unsigned int localAdapterNo,
unsigned int portNo,
unsigned int *data);
/*********************************************************************************/
/* Q U E R Y S Y S T E M */
/* */
/*********************************************************************************/
#define QuerySystem _SISCI_DEMOLIB_EXPAND_NAME(QuerySystem)
sci_error_t QuerySystem(
unsigned int subcommand,
unsigned int *data);
/*********************************************************************************/
/* D E T E C T F I R S T A D A P T E R C A R D */
/* */
/*********************************************************************************/
#define DetectFirstAdapterCard _SISCI_DEMOLIB_EXPAND_NAME(DetectFirstAdapterCard)
sci_error_t DetectFirstAdapterCard(
unsigned int *localAdapterNo,
unsigned int *localNodeId);
/*********************************************************************************/
/* G E T A D A P T E R T Y P E */
/* */
/*********************************************************************************/
#define GetAdapterType _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterType)
sci_error_t GetAdapterType(unsigned int localAdapterNo,
unsigned int *adapterType);
/*********************************************************************************/
/* G E T L O C A L N O D E I D */
/* */
/*********************************************************************************/
#define GetLocalNodeId _SISCI_DEMOLIB_EXPAND_NAME(GetLocalNodeId)
sci_error_t GetLocalNodeId(
unsigned int localAdapterNo,
unsigned int *localNodeId);
/*********************************************************************************/
/* G E T A D A P T E R S E R I A L N U M B E R */
/* */
/*********************************************************************************/
#define GetAdapterSerialNumber _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterSerialNumber)
sci_error_t GetAdapterSerialNumber(
unsigned int localAdapterNo,
unsigned int *serialNo);
/*********************************************************************************/
/* G E T H O S T B R I D G E T Y P E */
/* */
/*********************************************************************************/
#define GetHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(GetHostbridgeType)
sci_error_t GetHostbridgeType(unsigned int *hostbridgeType);
/*********************************************************************************/
/* P R I N T H O S T B R I D G E T Y P E */
/* */
/*********************************************************************************/
#define PrintHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(PrintHostbridgeType)
void PrintHostbridgeType(unsigned int hostbridge);
/*********************************************************************************/
/* G E T A P I V E R S I O N S T R I N G */
/* */
/*********************************************************************************/
#define GetAPIVersionString _SISCI_DEMOLIB_EXPAND_NAME(GetAPIVersionString)
sci_error_t GetAPIVersionString(char str[], unsigned int strLength);
/*********************************************************************************/
/* G E T A D A P T E R I O B U S F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterIoBusFrequency(unsigned int localAdapterNo,
unsigned int *ioBusFrequency);
/*********************************************************************************/
/* G E T A D A P T E R S C I L I N K F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterSciLinkFrequency(unsigned int localAdapterNo,
unsigned int *sciLinkFrequency);
/*********************************************************************************/
/* G E T A D A P T E R B L I N K F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterBlinkFrequency(unsigned int localAdapterNo,
unsigned int *bLinkFrequency);
/*********************************************************************************/
/* S E N D I N T E R R U P T */
/* */
/*********************************************************************************/
#define SendInterrupt _SISCI_DEMOLIB_EXPAND_NAME(SendInterrupt)
sci_error_t SendInterrupt(
sci_desc_t sd,
unsigned int localAdapterNo,
unsigned int localNodeId,
unsigned int remoteNodeId,
unsigned int interruptNo);
/*********************************************************************************/
/* R E C E I V E I N T E R R U P T */
/* */
/*********************************************************************************/
#define ReceiveInterrupt _SISCI_DEMOLIB_EXPAND_NAME(ReceiveInterrupt)
sci_error_t ReceiveInterrupt(
sci_desc_t sd,
unsigned int localAdapterNo,
unsigned int localNodeId,
unsigned int interruptNo);
/*********************************************************************************/
/* E N D I A N S W A P */
/* */
/*********************************************************************************/
#define EndianSwap _SISCI_DEMOLIB_EXPAND_NAME(EndianSwap)
unsigned int EndianSwap (unsigned int value);
/*********************************************************************************/
/* S L E E P M I L L I S E C O N D S */
/* */
/*********************************************************************************/
#define SleepMilliseconds _SISCI_DEMOLIB_EXPAND_NAME(SleepMilliseconds)
void SleepMilliseconds(int milliseconds);
#endif
/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_ERROR_H_
#define _SISCI_ERROR_H_
/* SCI Error return values always have 30 bit set */
#define SCI_ERR_MASK 0x40000000
#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
/* Error codes */
typedef enum {
SCI_ERR_OK = 0x000,
SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK)
} sci_error_t;
#endif /* _SCI_ERROR_H_ */
/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_TYPES_H
#define _SISCI_TYPES_H
#include "sisci_error.h"
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef IN_OUT
#define IN_OUT
#endif
/* Opaque data types for descriptors/handles */
typedef struct sci_desc *sci_desc_t;
typedef struct sci_local_segment *sci_local_segment_t;
typedef struct sci_remote_segment *sci_remote_segment_t;
typedef struct sci_map *sci_map_t;
typedef struct sci_sequence *sci_sequence_t;
#ifndef KERNEL
typedef struct sci_dma_queue *sci_dma_queue_t;
#endif
typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
typedef struct sci_local_interrupt *sci_local_interrupt_t;
typedef struct sci_block_transfer *sci_block_transfer_t;
/*
* Constants defining reasons for segment callbacks:
*/
typedef enum {
SCI_CB_CONNECT = 1,
SCI_CB_DISCONNECT,
SCI_CB_NOT_OPERATIONAL,
SCI_CB_OPERATIONAL,
SCI_CB_LOST
} sci_segment_cb_reason_t;
#define MAX_CB_REASON SCI_CB_LOST
/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
typedef enum {
SCI_DMAQUEUE_IDLE,
SCI_DMAQUEUE_GATHER,
SCI_DMAQUEUE_POSTED,
SCI_DMAQUEUE_DONE,
SCI_DMAQUEUE_ABORTED,
SCI_DMAQUEUE_ERROR
} sci_dma_queue_state_t;
typedef enum {
SCI_SEQ_OK,
SCI_SEQ_RETRIABLE,
SCI_SEQ_NOT_RETRIABLE,
SCI_SEQ_PENDING
} sci_sequence_status_t;
typedef struct {
unsigned short nodeId; /* SCI Address bit 63 - 48 */
unsigned short offsHi; /* SCI Address bit 47 - 32 */
unsigned int offsLo; /* SCI Address bit 31 - 0 */
} sci_address_t;
typedef unsigned int sci_ioaddr_t;
typedef enum {
SCI_CALLBACK_CANCEL = 1,
SCI_CALLBACK_CONTINUE
} sci_callback_action_t;
#ifndef KERNEL
typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
sci_local_segment_t segment,
sci_segment_cb_reason_t reason,
unsigned int nodeId,
unsigned int localAdapterNo,
sci_error_t error);
typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
sci_remote_segment_t segment,
sci_segment_cb_reason_t reason,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
sci_dma_queue_t queue,
sci_error_t status);
typedef int (*sci_cb_block_transfer_t)(void *arg,
sci_block_transfer_t block,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
sci_local_interrupt_t interrupt,
sci_error_t status);
#endif /* KERNEL */
#endif
/* $Id: sisci_version.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef SISCI_VERSION_H
#define SISCI_VERSION_H
#define SISCI_API_VER_MAJOR 0x01
#define SISCI_API_VER_MAJORC "1"
#define SISCI_API_VER_MINOR 0x010
#define SISCI_API_VER_MINORC "10"
#define SISCI_API_VER_MICRO 0x005
#define SISCI_API_VER_MICROC "5"
#define SISCI_SIGN_VERSION_MASK 0xfffff000 /* used to mask off API_VER_MICRO */
#define SISCI_API_VERSION (SISCI_API_VER_MAJOR << 24 | SISCI_API_VER_MINOR << 12 | SISCI_API_VER_MICRO)
/* the rules are:
*
* Changes in API_VER_MICRO should be binary compatible, New flags, functions added. No changes to user code
* required if new features is not needed.
*
* Changes in API_VER_MINOR requires recompilation of user code.
*
* Changes in the API_VER_MAJOR will most likely require changes to user code. This should not happen very
* often...
*
*/
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
#ifndef BUILD_NAME
#define BUILD_NAME ""
#endif
#define API_VERSION "SISCI API version " SISCI_API_VER_MAJORC "." SISCI_API_VER_MINORC "."SISCI_API_VER_MICROC " ( "BUILD_NAME" "BUILD_DATE" )"
#endif
/* Version info: */
/* */
/* 1.5.2 First SISCI version */
/* 1.5.3 Some bug fixes */
/* 1.5.4 Some bug fixes */
/* 1.5.5 No release */
/* 1.5.6 Lock flag implemented in function SCIConnectSegment */
/* 1.5.7 Expanded query functionality */
/* 1.5.8 Updated error checking (sequence) functionality for D320 */
/* 1.6.0 Updated error checking (sequence) D320 and IRM 1.9 support */
/* 1.9.0 Ported to Solaris_sparc, Solaris_x86 and Linux. IRM 1.9. */
/* 1.9.1 Some bug fixes */
/* 1.9.2 Added more adapter queries */
/* 1.9.3 Bug fix in SCIMapLocalSegment and SCIMapRemoteSegment */
/* 1.9.4 NT Release Developers Kit 2.40 */
/* 1.9.5 Added flush after data transfer in SCIMemCopy() */
/* 1.9.5 NT Release Developers Kit 2.44 */
/* 1.10.0:
* New SCIInitialize(), SCITerminate() functions.
* Support for D330
*
*
*/
#ifndef _VERSION_H
#define _VERSION_H
/*
#define DEMO_VER_MAJOR "1"
#define DEMO_VER_MINOR "5"
#define DEMO_VER_MICRO "0"
*/
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
#ifndef BUILD_NAME
#define BUILD_NAME ""
#endif
/*
#define DEMO_VERSION "version " DEMO_VER_MAJOR "." DEMO_VER_MINOR "."DEMO_VER_MICRO " ("BUILD_NAME" "BUILD_DATE" )"
*/
#define DEMO_VERSION " ("BUILD_NAME" "BUILD_DATE" )"
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_ERROR_H_
#define _SISCI_ERROR_H_
/* SCI Error return values always have 30 bit set */
#define SCI_ERR_MASK 0x40000000
#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
/* Error codes */
typedef enum {
SCI_ERR_OK = 0x000,
SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK)
} sci_error_t;
#endif /* _SCI_ERROR_H_ */
/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_TYPES_H
#define _SISCI_TYPES_H
#include "sisci_error.h"
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef IN_OUT
#define IN_OUT
#endif
/* Opaque data types for descriptors/handles */
typedef struct sci_desc *sci_desc_t;
typedef struct sci_local_segment *sci_local_segment_t;
typedef struct sci_remote_segment *sci_remote_segment_t;
typedef struct sci_map *sci_map_t;
typedef struct sci_sequence *sci_sequence_t;
#ifndef KERNEL
typedef struct sci_dma_queue *sci_dma_queue_t;
#endif
typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
typedef struct sci_local_interrupt *sci_local_interrupt_t;
typedef struct sci_block_transfer *sci_block_transfer_t;
/*
* Constants defining reasons for segment callbacks:
*/
typedef enum {
SCI_CB_CONNECT = 1,
SCI_CB_DISCONNECT,
SCI_CB_NOT_OPERATIONAL,
SCI_CB_OPERATIONAL,
SCI_CB_LOST
} sci_segment_cb_reason_t;
#define MAX_CB_REASON SCI_CB_LOST
/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
typedef enum {
SCI_DMAQUEUE_IDLE,
SCI_DMAQUEUE_GATHER,
SCI_DMAQUEUE_POSTED,
SCI_DMAQUEUE_DONE,
SCI_DMAQUEUE_ABORTED,
SCI_DMAQUEUE_ERROR
} sci_dma_queue_state_t;
typedef enum {
SCI_SEQ_OK,
SCI_SEQ_RETRIABLE,
SCI_SEQ_NOT_RETRIABLE,
SCI_SEQ_PENDING
} sci_sequence_status_t;
typedef struct {
unsigned short nodeId; /* SCI Address bit 63 - 48 */
unsigned short offsHi; /* SCI Address bit 47 - 32 */
unsigned int offsLo; /* SCI Address bit 31 - 0 */
} sci_address_t;
typedef unsigned int sci_ioaddr_t;
typedef enum {
SCI_CALLBACK_CANCEL = 1,
SCI_CALLBACK_CONTINUE
} sci_callback_action_t;
#ifndef KERNEL
typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
sci_local_segment_t segment,
sci_segment_cb_reason_t reason,
unsigned int nodeId,
unsigned int localAdapterNo,
sci_error_t error);
typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
sci_remote_segment_t segment,
sci_segment_cb_reason_t reason,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
sci_dma_queue_t queue,
sci_error_t status);
typedef int (*sci_cb_block_transfer_t)(void *arg,
sci_block_transfer_t block,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
sci_local_interrupt_t interrupt,
sci_error_t status);
#endif /* KERNEL */
#endif
/* $Id: sisci_version.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef SISCI_VERSION_H
#define SISCI_VERSION_H
#define SISCI_API_VER_MAJOR 1
#define SISCI_API_VER_MAJORC "1"
#define SISCI_API_VER_MINOR 10
#define SISCI_API_VER_MINORC "10"
#define SISCI_API_VER_MICRO 4
#define SISCI_API_VER_MICROC "4"
#define SISCI_SIGN_VERSION_MASK 0xfffff000 /* used to mask off API_VER_MICRO */
#define SISCI_API_VERSION (SISCI_API_VER_MAJOR << 24 | SISCI_API_VER_MINOR << 12 | SISCI_API_VER_MICRO)
/* the rules are:
*
* Changes in API_VER_MICRO should be binary compatible, New flags, functions added. No changes to user code
* required if new features is not needed.
*
* Changes in API_VER_MINOR requires recompilation of user code.
*
* Changes in the API_VER_MAJOR will most likely require changes to user code. This should not happen very
* often...
*
*/
#ifndef BUILD_DATE
#define BUILD_DATE __DATE__
#endif
#ifndef BUILD_NAME
#define BUILD_NAME ""
#endif
#define API_VERSION "SISCI API version " SISCI_API_VER_MAJORC "." SISCI_API_VER_MINORC "."SISCI_API_VER_MICROC " ( "BUILD_NAME" "BUILD_DATE" )"
#endif
/* Version info: */
/* */
/* 1.5.2 First SISCI version */
/* 1.5.3 Some bug fixes */
/* 1.5.4 Some bug fixes */
/* 1.5.5 No release */
/* 1.5.6 Lock flag implemented in function SCIConnectSegment */
/* 1.5.7 Expanded query functionality */
/* 1.5.8 Updated error checking (sequence) functionality for D320 */
/* 1.6.0 Updated error checking (sequence) D320 and IRM 1.9 support */
/* 1.9.0 Ported to Solaris_sparc, Solaris_x86 and Linux. IRM 1.9. */
/* 1.9.1 Some bug fixes */
/* 1.9.2 Added more adapter queries */
/* 1.9.3 Bug fix in SCIMapLocalSegment and SCIMapRemoteSegment */
/* 1.9.4 NT Release Developers Kit 2.40 */
/* 1.9.5 Added flush after data transfer in SCIMemCopy() */
/* 1.9.5 NT Release Developers Kit 2.44 */
/* 1.10.0:
* New SCIInitialize(), SCITerminate() functions.
* Support for D330
*
*
*/
/* $Id: rmlib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
/*********************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU Lesser General Public License as published by *
* the Free Software Foundation; either version 2.1 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU Lesser General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*********************************************************************************/
/********************************************************************************/
/* This header file contains the declarations of the SCI Reflective Memory */
/* library rmlib. The implementation of the library functions is in rmlib.c. */
/* The library contains all the functions that operate on the reflective */
/* memory. */
/* */
/* NB! */
/* */
/* DOLPHIN'S SCI REFLECTIVE MEMORY FILES ARE UNDER DEVELOPMENT AND MAY CHANGE. */
/* PLEASE CONTACT DOLPHIN FOR FURTHER INFORMATION. */
/* */
/* */
/********************************************************************************/
#include "sisci_error.h"
#include "sisci_api.h"
#include "sisci_demolib.h"
#include "sisci_types.h"
unsigned int seqerr, syncseqerr;
#ifndef _RMLIB_H
#define _RMLIB_H
#if defined(_REENTRANT)
#define _RMLIB_EXPAND_NAME(name) _RMLIB_MT_ ## name
#else
#define _RMLIB_EXPAND_NAME(name) _RMLIB_ST_ ## name
#endif
#ifdef __sparc
#define CACHE_SIZE 2097152
#else
#define CACHE_SIZE 8192
#endif
/*********************************************************************************/
/* FLAG VALUES */
/*********************************************************************************/
#define REFLECT_ERRCHECK 0x2
struct ReflectiveMemorySpace {
unsigned int localAdapterNo;
unsigned int localNodeId;
unsigned int remoteNodeId;
sci_desc_t sd;
sci_desc_t syncsd;
sci_map_t localMap;
sci_map_t remoteMap;
unsigned int localSegmentId;
unsigned int remoteSegmentId;
unsigned int syncSegmentId;
unsigned int sync_rSegmentId;
unsigned int segmentSize;
unsigned int *localMapAddr;
volatile unsigned int *remoteMapAddr;
sci_local_segment_t localSegment;
sci_remote_segment_t remoteSegment;
sci_local_segment_t syncSegment;
sci_remote_segment_t sync_rSegment;
sci_map_t syncMap;
sci_map_t sync_rMap;
sci_sequence_t syncsequence;
sci_sequence_t sequence;
unsigned int protection;
unsigned int retry_value;
sci_sequence_status_t sequenceStatus, syncsequenceStatus;
volatile unsigned int *syncMapAddr;
volatile unsigned int *sync_rMapAddr;
};
/*********************************************************************************/
/* P R I N T R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectPrintParameters _RMLIB_EXPAND_NAME(ReflectPrintParameters)
void ReflectPrintParameters(FILE *stream, struct ReflectiveMemorySpace RM_space);
/*********************************************************************************/
/* R E F L E C T D M A S E T U P */
/* */
/*********************************************************************************/
#define ReflectDmaSetup _RMLIB_EXPAND_NAME(ReflectDmaSetup)
sci_error_t ReflectDmaSetup(struct ReflectiveMemorySpace RM_space, sci_dma_queue_t *dmaQueue);
/*********************************************************************************/
/* R E F L E C T D M A R E M O V E */
/* */
/*********************************************************************************/
#define ReflectDmaRemove _RMLIB_EXPAND_NAME(ReflectDmaRemove)
sci_error_t ReflectDmaRemove(sci_dma_queue_t dmaQueue);
/*********************************************************************************/
/* R E F L E C T D M A R U N */
/* */
/*********************************************************************************/
#define ReflectDmaRun _RMLIB_EXPAND_NAME(ReflectDmaRun)
sci_error_t ReflectDmaRun(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset,
sci_dma_queue_t dmaQueue);
/*********************************************************************************/
/* C L O S E R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectClose _RMLIB_EXPAND_NAME(ReflectClose)
sci_error_t ReflectClose(struct ReflectiveMemorySpace RM_space, unsigned int segment_no);
/*********************************************************************************/
/* O P E N R E F L E C T I V E M E M O R Y S P A C E */
/* */
/*********************************************************************************/
#define ReflectOpen _RMLIB_EXPAND_NAME(ReflectOpen)
sci_error_t ReflectOpen(struct ReflectiveMemorySpace *RM_space,
unsigned int size,
unsigned int segment_no,
unsigned int localAdapterNo,
unsigned int remoteNodeId,
unsigned int protection,
unsigned int retry_value);
/*********************************************************************************/
/* R E F L E C T G E T A C C E S S */
/* */
/*********************************************************************************/
#define ReflectGetAccess _RMLIB_EXPAND_NAME(ReflectGetAccess)
sci_error_t ReflectGetAccess(struct ReflectiveMemorySpace *RM_space);
/*********************************************************************************/
/* R E F L E C T R E L E A S E A C C E S S */
/* */
/*********************************************************************************/
#define ReflectReleaseAccess _RMLIB_EXPAND_NAME(ReflectReleaseAccess)
sci_error_t ReflectReleaseAccess(struct ReflectiveMemorySpace *RM_space);
/*********************************************************************************/
/* R E F L E C T D M A */
/* */
/*********************************************************************************/
#define ReflectDma _RMLIB_EXPAND_NAME(ReflectDma)
sci_error_t ReflectDma(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset);
/*********************************************************************************/
/* R E F L E C T M E M C O P Y */
/* */
/*********************************************************************************/
#define ReflectMemCopy _RMLIB_EXPAND_NAME(ReflectMemCopy)
sci_error_t ReflectMemCopy(struct ReflectiveMemorySpace RM_space,
unsigned int* privateSrc,
unsigned int size,
unsigned int offset,
unsigned int flags);
/*********************************************************************************/
/* R E F L E C T S E T */
/* */
/*********************************************************************************/
#define ReflectSet _RMLIB_EXPAND_NAME(ReflectSet)
sci_error_t ReflectSet(struct ReflectiveMemorySpace RM_space,
unsigned int value,
unsigned int size,
unsigned int offset,
unsigned int flags
);
/*********************************************************************************/
/* R E F L E C T P R I N T */
/* */
/*********************************************************************************/
#define ReflectPrint _RMLIB_EXPAND_NAME(ReflectPrint)
sci_error_t ReflectPrint(FILE *stream,
struct ReflectiveMemorySpace RM_space,
unsigned int size,
unsigned int offset
);
#endif
/* $Id: scilib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 2002 *
* Dolphin Interconnect Solutions AS *
* *
*******************************************************************************/
#if defined(_REENTRANT)
#define _SCIL_EXPANDE_FUNCTION_NAME(name) _SCIL_PUBLIC_FUNC_MT_ ## name
#define _SCIL_EXPANDE_VARIABLE_NAME(name) _SCIL_PUBLIC_VAR_MT_ ## name
#else
#define _SCIL_EXPANDE_FUNCTION_NAME(name) _SCIL_PUBLIC_FUNC_ST_ ## name
#define _SCIL_EXPANDE_VARIABLE_NAME(name) _SCIL_PUBLIC_VAR_ST_ ## name
#endif
#define _SCIL_EXPANDE_CONSTANT_NAME(name) _SCIL_PUBLIC_CONST_ ## name
#include "sisci_api.h"
#if defined(CPLUSPLUS) || defined(__cplusplus)
extern "C" {
#endif
/*
* SISCI segment id pollution:
* ===========================
* The SISCI library uses regular SISCI segmens internally.
* The MSG_QUEUE_LIB_IDENTIFIER_MASK is a mask which is used by the SISCI
* library to identify internal SISCI segments ids, from segments used directly
* by the user.
*
* Future versions of the library may have its own namespace.
*
*/
#define MSG_QUEUE_LIB_IDENTIFIER_MASK 0x10000000
/*********************************************************************************/
/* FLAG VALUES */
/*********************************************************************************/
#define SCIL_FLAG_ERROR_CHECK_DATA _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_ERROR_CHECK_DATA)
extern const unsigned int SCIL_FLAG_ERROR_CHECK_DATA;
#define SCIL_FLAG_ERROR_CHECK_PROT _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_ERROR_CHECK_PROT)
extern const unsigned int SCIL_FLAG_ERROR_CHECK_PROT;
#define SCIL_FLAG_FULL_ERROR_CHECK _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_FULL_ERROR_CHECK)
extern const unsigned int SCIL_FLAG_FULL_ERROR_CHECK;
typedef struct sci_msq_queue *sci_msq_queue_t;
/*********************************************************************************
* *
* S C I L C r e a t e M s g Q u e u e *
* *
* Parameters: *
* *
* Creates a message queue. The message queue identifier object will be allocated*
* if the sci_msq_queue_t * msg pointer is NULL. The function will create a *
* remote connection. If this connection times out, the function shoud be *
* repeated until connection is established. SCILRemoveMsgQueue() must be called *
* to remove the connection and deallocate the message queue identifier. *
* *
* sci_msq_queue_t *msq : Message queue identifier *
* The function must be called with a null pointer *
* the first time. *
* unsigned int localAdapterNo: Local Adapter Number *
* unsigned int remoteNodeId : Remote nodeId *
* unsigned int msqId : Message queue number *
* unsigned int maxMsgCount : The maximum count of messages in queue *
* unsigned int maxMsgSize, : The maximum size of each messages in queue *
* unsigned int timeout : Time to wait for successful connection *
* unsigned int flags : Flags. *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None. Normal SISIC error codes. *
* *
*********************************************************************************/
#define SCILCreateMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILCreateMsgQueue)
DLL sci_error_t SCILCreateMsgQueue(sci_msq_queue_t *msq,
unsigned int localAdapterNo,
unsigned int remoteNodeId,
unsigned int msqId,
unsigned int maxMsgCount,
unsigned int maxMsgSize,
unsigned int timeout,
unsigned int flags);
/*********************************************************************************
* *
* S C I L R e c e i v e M s g *
* *
* *
* Receives a message from the queue. *
* *
* Paremeters *
* *
* sci_msq_queue_t msq : message queue identifier *
* void *msg : Location to store received data *
* unsigned int size : Size of message to read *
* unsigned int *sizeLeft: Bytes left in buffer, after current receive. This is *
* just a hint. There may be more. *
* *
* Flags *
* *
* SCIL_FLAG_ERROR_CHECK_PROT: The internal buffer management is done using full*
* error checking.
* *
* Specific error codes for this function: *
* *
* SCI_ERR_EWOULD_BLOCK : There is not enough data in the message buffer *
* to read the specified number of bytes. *
* . *
* SCI_ERR_NOT_CONNECTED : The connection is not established. *
* *
*********************************************************************************/
#define SCILReceiveMsg _SCIL_EXPANDE_FUNCTION_NAME(SCILReceiveMsg)
DLL sci_error_t SCILReceiveMsg(
sci_msq_queue_t msq,
void *msg,
unsigned int size,
unsigned int *sizeLeft,
unsigned int flags);
/*********************************************************************************
* *
* S C I L S e n d M s g *
* *
* *
* Sends a message to the queue. *
* *
* Paremeters *
* *
* sci_msq_queue_t msq : Message queue identifier *
* void *msg : Send data *
* unsigned int size : Size of message to send *
* unsigned int *sizeFree: Bytes free in buffer, after current send. This is *
* just a hint. There may be more. *
* *
* Flags *
* *
* SCIL_FLAG_ERROR_CHECK_DATA: The data is transmitted using full error checking*
* SCIL_FLAG_ERROR_CHECK_PROT: The internal buffer management is done using full*
* error checking. *
* SCIL_FLSG_FULL_ERROR_CHECK: This flag is an combination of both above. *
* *
* Specific error codes for this function: *
* *
* SCI_ERR_EWOULD_BLOCK : There is not enough data in the message buffer *
* to send the specified number of bytes. *
* . *
* SCI_ERR_NOT_CONNECTED : The connection is not established. *
* *
*********************************************************************************/
#define SCILSendMsg _SCIL_EXPANDE_FUNCTION_NAME(SCILSendMsg)
DLL sci_error_t SCILSendMsg(
sci_msq_queue_t msq,
void *msg,
unsigned int size,
unsigned int *sizeFree,
unsigned int flags);
/*********************************************************************************
* *
* S C I L R e m o v e M s g Q u e ue *
* *
* *
* Removes a message queue. *
* *
* sci_msq_queue_t msq : Message queue identifier *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None *
* *
*********************************************************************************/
#define SCILRemoveMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILRemoveMsgQueue)
DLL sci_error_t SCILRemoveMsgQueue(
sci_msq_queue_t *msq,
unsigned int flags);
/*********************************************************************************
* *
* S C I L I n i t *
* *
* *
* Initializes the SCI library. This function must be called before any other *
* function in the library. *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None *
* . *
*********************************************************************************/
#define SCILInit _SCIL_EXPANDE_FUNCTION_NAME(SCILInit)
DLL sci_error_t SCILInit(unsigned int flags);
/*********************************************************************************
* *
* S C I L D e s t r o y *
* *
* *
* Removes internal resources allocated by the SCI Library. No other library *
* function should be called after this function. *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None *
* *
*********************************************************************************/
#define SCILDestroy _SCIL_EXPANDE_FUNCTION_NAME(SCILDestroy)
DLL sci_error_t SCILDestroy(unsigned int flags);
/*********************************************************************************
* *
* S C I L C o n n e c t M s g Q u e u e *
* *
* *
* Makes a connection to a remote message queue. This must be done before *
* SCILSendMsg() is called. *
* *
* Parameters: *
* *
* sci_msq_queue_t *msq : Message queue identifier *
* unsigned int localAdapterNo: Local Adapter Number *
* unsigned int remoteNodeId : Remote nodeId *
* unsigned int msqId : Message queue number *
* unsigned int maxMsgCount : The maximum count of messages in queue *
* unsigned int maxMsgSize, : The maximum size of each messages in queue *
* unsigned int timeout : Time to wait for successful connection *
* unsigned int flags : Flags. *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None. Normal SISIC error codes. *
* *
*********************************************************************************/
#define SCILConnectMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILConnectMsgQueue)
DLL sci_error_t SCILConnectMsgQueue(sci_msq_queue_t *msq,
unsigned int localAdapterNo,
unsigned int remoteNodeId,
unsigned int rmsgId,
unsigned int maxMsgCount,
unsigned int maxMsgSize,
unsigned int timeout,
unsigned int flags);
/*********************************************************************************
* *
* S C I L D i s c o n n e c t M s g Q u e u e *
* *
* *
* Disconnects from a remote message queue. *
* *
* Parameters: *
* *
* sci_msq_queue_t *msq : Message queue identifier *
* *
* Flags *
* *
* None *
* *
* Specific error codes for this function: *
* *
* None *
* *
*********************************************************************************/
#define SCILDisconnectMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILDisconnectMsgQueue)
DLL sci_error_t SCILDisconnectMsgQueue(sci_msq_queue_t *msq,
unsigned int flags);
#if defined(CPLUSPLUS) || defined(__cplusplus)
}
#endif
This source diff could not be displayed because it is too large. You can view the blob instead.
/* $Id: sisci_demolib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_DEMOLIB_H
#define _SISCI_DEMOLIB_H
#if defined(_REENTRANT)
#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_MT_ ## name
#else
#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_ST_ ## name
#endif
/*********************************************************************************/
/* Q U E R Y A D A P T E R */
/* */
/*********************************************************************************/
#define QueryAdapter _SISCI_DEMOLIB_EXPAND_NAME(QueryAdapter)
sci_error_t QueryAdapter(
unsigned int subcommand,
unsigned int localAdapterNo,
unsigned int portNo,
unsigned int *data);
/*********************************************************************************/
/* Q U E R Y S Y S T E M */
/* */
/*********************************************************************************/
#define QuerySystem _SISCI_DEMOLIB_EXPAND_NAME(QuerySystem)
sci_error_t QuerySystem(
unsigned int subcommand,
unsigned int *data);
/*********************************************************************************/
/* D E T E C T F I R S T A D A P T E R C A R D */
/* */
/*********************************************************************************/
#define DetectFirstAdapterCard _SISCI_DEMOLIB_EXPAND_NAME(DetectFirstAdapterCard)
sci_error_t DetectFirstAdapterCard(
unsigned int *localAdapterNo,
unsigned int *localNodeId);
/*********************************************************************************/
/* G E T A D A P T E R T Y P E */
/* */
/*********************************************************************************/
#define GetAdapterType _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterType)
sci_error_t GetAdapterType(unsigned int localAdapterNo,
unsigned int *adapterType);
/*********************************************************************************/
/* G E T L O C A L N O D E I D */
/* */
/*********************************************************************************/
#define GetLocalNodeId _SISCI_DEMOLIB_EXPAND_NAME(GetLocalNodeId)
sci_error_t GetLocalNodeId(
unsigned int localAdapterNo,
unsigned int *localNodeId);
/*********************************************************************************/
/* G E T A D A P T E R S E R I A L N U M B E R */
/* */
/*********************************************************************************/
#define GetAdapterSerialNumber _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterSerialNumber)
sci_error_t GetAdapterSerialNumber(
unsigned int localAdapterNo,
unsigned int *serialNo);
/*********************************************************************************/
/* G E T H O S T B R I D G E T Y P E */
/* */
/*********************************************************************************/
#define GetHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(GetHostbridgeType)
sci_error_t GetHostbridgeType(unsigned int *hostbridgeType);
/*********************************************************************************/
/* P R I N T H O S T B R I D G E T Y P E */
/* */
/*********************************************************************************/
#define PrintHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(PrintHostbridgeType)
void PrintHostbridgeType(unsigned int hostbridge);
/*********************************************************************************/
/* G E T A P I V E R S I O N S T R I N G */
/* */
/*********************************************************************************/
#define GetAPIVersionString _SISCI_DEMOLIB_EXPAND_NAME(GetAPIVersionString)
sci_error_t GetAPIVersionString(char str[], unsigned int strLength);
/*********************************************************************************/
/* G E T A D A P T E R I O B U S F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterIoBusFrequency(unsigned int localAdapterNo,
unsigned int *ioBusFrequency);
/*********************************************************************************/
/* G E T A D A P T E R S C I L I N K F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterSciLinkFrequency(unsigned int localAdapterNo,
unsigned int *sciLinkFrequency);
/*********************************************************************************/
/* G E T A D A P T E R B L I N K F R E Q U E N C Y */
/* */
/*********************************************************************************/
sci_error_t GetAdapterBlinkFrequency(unsigned int localAdapterNo,
unsigned int *bLinkFrequency);
/*********************************************************************************/
/* S E N D I N T E R R U P T */
/* */
/*********************************************************************************/
#define SendInterrupt _SISCI_DEMOLIB_EXPAND_NAME(SendInterrupt)
sci_error_t SendInterrupt(
sci_desc_t sd,
unsigned int localAdapterNo,
unsigned int localNodeId,
unsigned int remoteNodeId,
unsigned int interruptNo);
/*********************************************************************************/
/* R E C E I V E I N T E R R U P T */
/* */
/*********************************************************************************/
#define ReceiveInterrupt _SISCI_DEMOLIB_EXPAND_NAME(ReceiveInterrupt)
sci_error_t ReceiveInterrupt(
sci_desc_t sd,
unsigned int localAdapterNo,
unsigned int localNodeId,
unsigned int interruptNo);
/*********************************************************************************/
/* E N D I A N S W A P */
/* */
/*********************************************************************************/
#define EndianSwap _SISCI_DEMOLIB_EXPAND_NAME(EndianSwap)
unsigned int EndianSwap (unsigned int value);
/*********************************************************************************/
/* S L E E P M I L L I S E C O N D S */
/* */
/*********************************************************************************/
#define SleepMilliseconds _SISCI_DEMOLIB_EXPAND_NAME(SleepMilliseconds)
void SleepMilliseconds(int milliseconds);
#endif
/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_ERROR_H_
#define _SISCI_ERROR_H_
/* SCI Error return values always have 30 bit set */
#define SCI_ERR_MASK 0x40000000
#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
/* Error codes */
typedef enum {
SCI_ERR_OK = 0x000,
SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK),
SCI_ERR_EWOULD_BLOCK = ( 0xB00 | SCI_ERR_MASK),
SCI_ERR_SEMAPHORE_COUNT_EXCEEDED = ( 0xB01 | SCI_ERR_MASK),
SCI_ERR_IRQL_ILLEGAL = ( 0xB02 | SCI_ERR_MASK)
} sci_error_t;
#endif /* _SCI_ERROR_H_ */
/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
/*******************************************************************************
* *
* Copyright (C) 1993 - 2000 *
* Dolphin Interconnect Solutions AS *
* *
* This program is free software; you can redistribute it and/or modify *
* it under the terms of the GNU General Public License as published by *
* the Free Software Foundation; either version 2 of the License, *
* or (at your option) any later version. *
* *
* This program is distributed in the hope that it will be useful, *
* but WITHOUT ANY WARRANTY; without even the implied warranty of *
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the *
* GNU General Public License for more details. *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the Free Software *
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
* *
* *
*******************************************************************************/
#ifndef _SISCI_TYPES_H
#define _SISCI_TYPES_H
#include "sisci_error.h"
#ifndef IN
#define IN
#endif
#ifndef OUT
#define OUT
#endif
#ifndef IN_OUT
#define IN_OUT
#endif
/* Opaque data types for descriptors/handles */
typedef struct sci_desc *sci_desc_t;
typedef struct sci_local_segment *sci_local_segment_t;
typedef struct sci_remote_segment *sci_remote_segment_t;
typedef struct sci_map *sci_map_t;
typedef struct sci_sequence *sci_sequence_t;
#ifndef KERNEL
typedef struct sci_dma_queue *sci_dma_queue_t;
#endif
typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
typedef struct sci_local_interrupt *sci_local_interrupt_t;
typedef struct sci_block_transfer *sci_block_transfer_t;
/*
* Constants defining reasons for segment callbacks:
*/
typedef enum {
SCI_CB_CONNECT = 1,
SCI_CB_DISCONNECT,
SCI_CB_NOT_OPERATIONAL,
SCI_CB_OPERATIONAL,
SCI_CB_LOST
} sci_segment_cb_reason_t;
#define MAX_CB_REASON SCI_CB_LOST
/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
typedef enum {
SCI_DMAQUEUE_IDLE,
SCI_DMAQUEUE_GATHER,
SCI_DMAQUEUE_POSTED,
SCI_DMAQUEUE_DONE,
SCI_DMAQUEUE_ABORTED,
SCI_DMAQUEUE_ERROR
} sci_dma_queue_state_t;
typedef enum {
SCI_SEQ_OK,
SCI_SEQ_RETRIABLE,
SCI_SEQ_NOT_RETRIABLE,
SCI_SEQ_PENDING
} sci_sequence_status_t;
typedef struct {
unsigned short nodeId; /* SCI Address bit 63 - 48 */
unsigned short offsHi; /* SCI Address bit 47 - 32 */
unsigned int offsLo; /* SCI Address bit 31 - 0 */
} sci_address_t;
typedef unsigned int sci_ioaddr_t;
typedef enum {
SCI_CALLBACK_CANCEL = 1,
SCI_CALLBACK_CONTINUE
} sci_callback_action_t;
#ifndef KERNEL
typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
sci_local_segment_t segment,
sci_segment_cb_reason_t reason,
unsigned int nodeId,
unsigned int localAdapterNo,
sci_error_t error);
typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
sci_remote_segment_t segment,
sci_segment_cb_reason_t reason,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
sci_dma_queue_t queue,
sci_error_t status);
typedef int (*sci_cb_block_transfer_t)(void *arg,
sci_block_transfer_t block,
sci_error_t status);
typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
sci_local_interrupt_t interrupt,
sci_error_t status);
#endif /* KERNEL */
#endif
include .defs.mk
TYPE = *
BIN_TARGET = tpcb
SOURCES = ttTime.c tpcb.cpp
CCFLAGS_LOC += \
-I$(NDB_TOP)/include \
-I$(NDB_TOP)/include/ndbapi \
-I$(NDB_TOP)/include/portlib \
-I$(NDB_TOP)/include/util \
-I$(NDB_TOP)/test/include \
-I/usr/local/include
CCFLAGS_WARNINGS += -Wno-unused -Wno-sign-compare -Wformat
CCFLAGS_TOP += -DndbODBC
BIN_TARGET_LIBS = NDB_API_pic NDB_ODBC_pic NDBT
ifeq ($(NDB_OS),SOLARIS)
BIN_TARGET_LIBS += dmallocthcxx
CCFLAGS_TOP += -DDMALLOC
endif
include $(NDB_TOP)/Epilogue.mk
$(BIN_DIR)$(BIN_TARGET): Makefile
include $(NDB_TOP)/Defs.mk
TYPE = odbcclient
BIN_TARGET = tpcb
SOURCES = ttTime.c tpcb.cpp
CCFLAGS_LOC += -I/usr/local/include \
-I$(NDB_TOP)/test/include \
-I$(NDB_TOP)/include \
-I$(NDB_TOP)/include/util \
-I$(NDB_TOP)/src/client/odbc/common
#CCFLAGS_WARNINGS += -Wno-unused
LIBS_LOC += -L/usr/local/lib
BIN_TARGET_LIBS_DIRS += /usr/local/lib
BIN_TARGET_LIBS += odbc odbcinst
#LIBS_SPEC += -pg
# -lNDBT \
# -lodbc \
# -lodbcinst \
# -lportlib
include $(NDB_TOP)/Epilogue.mk
include $(NDB_TOP)/Defs.mk
TYPE = *
BIN_TARGET = tpcb
SOURCES = ttTime.c tpcb.cpp
CCFLAGS_LOC += \
-I$(NDB_TOP)/include \
-I$(NDB_TOP)/include/ndbapi \
-I$(NDB_TOP)/include/portlib \
-I$(NDB_TOP)/include/util \
-I$(NDB_TOP)/test/include \
-I/usr/local/include
CCFLAGS_WARNINGS += -Wno-unused -Wno-sign-compare -Wformat
CCFLAGS_TOP += -DndbODBC
BIN_TARGET_LIBS = NDB_API_pic NDB_ODBC_pic NDBT
ifeq ($(NDB_OS),SOLARIS)
BIN_TARGET_LIBS += dmallocthcxx
CCFLAGS_TOP += -DDMALLOC
endif
include $(NDB_TOP)/Epilogue.mk
$(BIN_DIR)$(BIN_TARGET): Makefile
'tpcb' requires an .odbc.ini file in
/etc/
or in
/home/user/
The .odbc.ini file must contain a DSN entry called ndb:
#--------- .odbc.ini example --------------------
[ndb]
Driver = /path_to_installation/lib/libNDB_ODBC.so
#--------- End of example -----------------------
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
* $Revision: 1.1 $
* (c) Copyright 1997-2003, TimesTen, Inc.
* All rights reserved.
*/
#ifndef TIMESTEN_H_INCLUDED
#define TIMESTEN_H_INCLUDED
#ifdef _WIN32
#include <windows.h>
#endif
#include <sql.h>
#include <sqltypes.h>
#include <sqlext.h>
/*
* TimesTen extension to application data types; only usable
* when application directly linked to the TimesTen driver.
*/
#define SQL_C_ADDR 100
#ifndef SQL_C_SBIGINT
#if (ODBCVER < 0x0300)
#define SQL_C_SBIGINT (SQL_BIGINT+SQL_SIGNED_OFFSET)
#define SQL_C_UBIGINT (SQL_BIGINT+SQL_UNSIGNED_OFFSET)
#endif
#endif
#define SQL_C_BIGINT SQL_C_SBIGINT
#if (ODBCVER < 0x0300)
#ifdef _WIN32
typedef __int64 SQLBIGINT;
/* On Unix platforms SQLBIGINT is defined in odbcinclude directory*/
#endif
#endif
#define BIGINT SQLBIGINT
#ifdef _WIN32
#define UBIGINT unsigned __int64
#else
#define UBIGINT unsigned long long
#endif
#define SQL_WCHAR (-8)
#define SQL_WVARCHAR (-9)
#define SQL_WLONGVARCHAR (-10)
#define SQL_C_WCHAR SQL_WCHAR
/* SQLGetInfo() InfoTypes */
#define SQL_CONVERT_WCHAR 122
#define SQL_CONVERT_WLONGVARCHAR 125
#define SQL_CONVERT_WVARCHAR 126
/* TimesTen specific SQLGetInfo types */
#define TT_REPLICATION_INVALID (SQL_INFO_DRIVER_START + 2000)
/* SQLGetInfo() return value bitmasks */
#ifndef SQL_CVT_WCHAR
/*
** These definitions differ from Microsoft in that they are not
** specified as long (e.g. 0x00200000L), hence they are protected
** by the ifndef above.
*/
#define SQL_CVT_WCHAR 0x00200000
#define SQL_CVT_WLONGVARCHAR 0x00400000
#define SQL_CVT_WVARCHAR 0x00800000
#endif
/*
** The Microsoft Driver Manager SQLBindParameter() will not pass SQL_WCHAR
** through. Use this hack to get around it.
*/
#define SQL_WCHAR_DM_SQLBINDPARAMETER_BYPASS -888
/* This is an extension to ODBC's isolation levels. It reflects an
* earlier implementation of read-committed that released locks on
* next fetch, rather than releasing locks before returning value to
* application. */
#define SQL_TXN_CURSOR_STABILITY 0x00001000
#define SQL_TXN_NOBLOCK_DELETE 0x00002000
/* TimesTen-specific connection option */
#define TT_PREFETCH_CLOSE 10001
#define TT_PREFETCH_CLOSE_OFF 0
#define TT_PREFETCH_CLOSE_ON 1
/* Adding a new sql connection option */
#define TT_PREFETCH_COUNT 10003
#define TT_PREFETCH_COUNT_MAX 128
/*
* Platform specific data types for integers that scale
* with pointer size
*/
#ifdef _IA64_
typedef signed __int64 tt_ptrint;
typedef unsigned __int64 tt_uptrint;
#else
#ifdef _WIN32
typedef signed long tt_ptrint;
typedef unsigned long tt_uptrint;
#else
typedef signed long tt_ptrint;
typedef unsigned long tt_uptrint;
#endif
#endif
#ifdef _WIN32
typedef signed __int64 tt_int8;
typedef unsigned __int64 tt_uint8;
#else
typedef signed long long tt_int8;
typedef unsigned long long tt_uint8;
#endif
/* printf formats for pointer-sized integers */
#ifdef _IA64_ /* 64-bit NT */
#define PTRINT_FMT "I64d"
#define UPTRINT_FMT "I64u"
#define xPTRINT_FMT "I64x"
#define XPTRINT_FMT "I64X"
#else
#ifdef _WIN32 /* 32-bit NT */
#define PTRINT_FMT "ld"
#define UPTRINT_FMT "lu"
#define xPTRINT_FMT "lx"
#define XPTRINT_FMT "lX"
#else /* 32 and 64-bit UNIX */
#define PTRINT_FMT "ld"
#define UPTRINT_FMT "lu"
#define xPTRINT_FMT "lx"
#define XPTRINT_FMT "lX"
#endif
#endif
/* printf formats for 8-byte integers */
#ifndef INT8_FMT_DEFINED
#ifdef _WIN32 /* 32 and 64-bit NT */
#define INT8_FMT "I64d"
#define UINT8_FMT "I64u"
#define xINT8_FMT "I64x"
#define XINT8_FMT "I64X"
#else /* 32 and 64-bit UNIX */
#define INT8_FMT "lld"
#define UINT8_FMT "llu"
#define xINT8_FMT "llx"
#define XINT8_FMT "llX"
#endif
#define INT8_FMT_DEFINED 1
#endif
/* The following types are defined in the newer odbc include files
from Microsoft
*/
#if defined (_WIN32) && !defined (_IA64_)
#ifndef SQLROWSETSIZE
#define SQLROWSETSIZE SQLUINTEGER
#define SQLLEN SQLINTEGER
#define SQLROWOFFSET SQLINTEGER
#define SQLROWCOUNT SQLUINTEGER
#define SQLULEN SQLUINTEGER
#define SQLSETPOSIROW SQLUSMALLINT
#endif
#endif
#endif
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
static const volatile char cvsid[] = "$Id: tpcb.cpp,v 1.4 2003/09/26 09:04:34 johan Exp $";
/*
* $Revision: 1.4 $
* (c) Copyright 1996-2003, TimesTen, Inc.
* All rights reserved.
*/
/* This source is best displayed with a tabstop of 4 */
#define NDB
//#define MYSQL
#ifdef WIN32
#include <windows.h>
#include "ttRand.h"
#else
#if !defined NDB && !defined MYSQL
#include <sqlunix.h>
#endif
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef SB_P_OS_CHORUS
#include "ttRand.h"
#endif
#endif
#include <math.h>
#include <time.h>
#include <sql.h>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#if !defined NDB && !defined MYSQL
#include "ttTime.h"
#include "utils.h"
#include "tt_version.h"
#include "timesten.h"
#endif
#if defined NDB || defined MYSQL
#include <NdbOut.hpp>
#include <string.h>
#include <sqlext.h>
#include <sql.h>
extern "C" {
#include "ttTime.h"
#include "timesten.h"
void ttGetWallClockTime(ttWallClockTime* timeP);
void ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
ttWallClockTime* afterP,
double* nmillisecondsP);
void ttGetThreadTimes(ttThreadTimes * endRes);
void ttCalcElapsedThreadTimes(ttThreadTimes* startRes,
ttThreadTimes * endRes,
double * kernel,
double * user);
}
#define app_exit exit
#define status_msg0 ndbout_c
#define status_msg1 ndbout_c
#define status_msg2 ndbout_c
#define err_msg0 ndbout_c
#define err_msg1 ndbout_c
#define err_msg3 ndbout_c
#define out_msg0 ndbout_c
#define out_msg1 ndbout_c
#define out_msg3 ndbout_c
#define CONN_STR_LEN 255
#define DBMS_TIMESTEN 1
#define DBMS_MSSQL 2
#define DBMS_UNKNOWN 3
#define ABORT_DISCONNECT_EXIT 1
#define NO_EXIT 0
#define ERROR_EXIT 1
#define DISCONNECT_EXIT 2
#endif
#define VERBOSE_NOMSGS 0
/* this value is used for results (and err msgs) only */
#define VERBOSE_RESULTS 1
/* this value is the default for the cmdline demo */
#define VERBOSE_DFLT 2
#define VERBOSE_ALL 3
#ifdef MYSQL
#define DSNNAME "DSN=myodbc3"
#elif defined NDB
#define DSNNAME "DSN=ndb"
#else
#define DSNNAME "DSN="
#endif
/* number of branches, tellers, and accounts */
#define NumBranches 1
#define TellersPerBranch 10
#define AccountsPerBranch 10000
/* number of transactions to execute */
#define NumXacts 25000
/* starting seed value for the random number generator */
#define SeedVal 84773
/* for MS SQL, the drop, create and use database statements */
#define DatabaseDropStmt "drop database tpcbDB;"
#ifdef MYSQL
#define DatabaseCreateStmt "create database tpcbDB;"
#else
#define DatabaseCreateStmt "create database tpcbDB ON DEFAULT = %d;"
#endif
#define DatabaseUseStmt "use tpcbDB;"
/*
* Specifications of table columns.
* Fillers of 80, 80, 84, and 24 bytes, respectively, are used
* to ensure that rows are the width required by the benchmark.
*
* Note: The TimesTen and MS SQL CREATE TABLE statements for the
* accounts, tellers and branches tables are different.
*
*/
#define TuplesPerPage 256
#ifdef MYSQL
#define AccountCrTblStmt "create table accounts \
(number integer not null primary key, \
branchnum integer not null, \
balance float not null, \
filler char(80));"
#define TellerCrTblStmt "create table tellers \
(number integer not null primary key, \
branchnum integer not null, \
balance float not null, \
filler char(80));"
#define BranchCrTblStmt "create table branches \
(number integer not null primary key, \
balance float not null, \
filler char(84));"
#endif
#ifdef NDB
#define AccountCrTblStmt "create table accounts \
(number integer not null primary key, \
branchnum integer not null, \
balance float not null, \
filler char(80)) nologging"
#define TellerCrTblStmt "create table tellers \
(number integer not null primary key, \
branchnum integer not null, \
balance float not null, \
filler char(80)) nologging"
#define BranchCrTblStmt "create table branches \
(number integer not null primary key, \
balance float not null, \
filler char(84)) nologging"
#endif
#ifdef NDB
#define HistoryCrTblStmt "create table History \
(tellernum integer not null, \
branchnum integer not null, \
accountnum integer not null, \
delta float not null, \
createtime integer not null, \
filler char(24), \
primary key (tellernum, branchnum, accountnum, delta, createtime)) nologging"
#else
#ifdef MYSQL
#define HistoryCrTblStmt "create table History \
(tellernum integer not null, \
branchnum integer not null, \
accountnum integer not null, \
delta float(53) not null, \
createtime integer not null, \
filler char(24))"
#endif
#define HistoryCrTblStmt "create table History \
(tellernum integer not null, \
branchnum integer not null, \
accountnum integer not null, \
delta float(53) not null, \
createtime integer not null, \
filler char(24));"
#endif
#define TTAccountCrTblStmt "create table accounts \
(number integer not null primary key, \
branchnum integer not null, \
balance float(53) not null, \
filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
#define TTTellerCrTblStmt "create table tellers \
(number integer not null primary key, \
branchnum integer not null, \
balance float(53) not null, \
filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
#define TTBranchCrTblStmt "create table branches \
(number integer not null primary key, \
balance float(53) not null, \
filler char(84)) unique hash on (number) pages = %" PTRINT_FMT ";"
/* Insertion statements used to populate the tables */
#define NumInsStmts 3
char* insStmt[NumInsStmts] = {
"insert into branches values (?, 0.0, NULL)",
"insert into tellers values (?, ?, 0.0, NULL)",
"insert into accounts values (?, ?, 0.0, NULL)"
};
/* Transaction statements used to update the tables */
#define NumXactStmts 5
#ifdef NDB
char* tpcbXactStmt[NumXactStmts] = {
"update accounts \
set balance = balance + ? \
where number = ?",
"select balance \
from accounts \
where number = ?",
"update tellers \
set balance = balance + ? \
where number = ?",
"update branches \
set balance = balance + ? \
where number = ?",
"insert into History(tellernum, branchnum, \
accountnum, delta, createtime, filler) \
values (?, ?, ?, ?, ?, NULL)"
};
#else
char* tpcbXactStmt[NumXactStmts] = {
"update accounts \
set balance = balance + ? \
where number = ?;",
"select balance \
from accounts \
where number = ?;",
"update tellers \
set balance = balance + ? \
where number = ?;",
"update branches \
set balance = balance + ? \
where number = ?;",
"insert into History \
values (?, ?, ?, ?, ?, NULL);"
};
#endif
/* Global parameters and flags (typically set by parse_args()) */
int tabFlag = 0; /* Default is NOT tab output mode */
char szConnStrIn[CONN_STR_LEN]; /* ODBC Connection String */
int printXactTimes = 0; /* Transaction statistics
* gathering flag */
char statFile[FILENAME_MAX]; /* Transaction statistics filename */
int scaleFactor = 2; /* Default TPS scale factor */
int numBranchTups; /* Number of branches */
int numTellerTups; /* Number of tellers */
int numAccountTups; /* Number of accounts */
int numNonLocalAccountTups; /* Number of local accounts */
int numXacts = NumXacts; /* Default number of transactions */
int verbose = VERBOSE_DFLT; /* Verbose level */
FILE *statusfp; /* File for status messages */
int DBMSType; /* DBMS type (DBMS_TIMESTEN, DBMS_MSSQL...) */
SQLHENV henv; /* Environment handle */
void handle_errors( SQLHDBC hdbc, SQLHSTMT hstmt, int errcode, int action, char * msg,
char * file, int line) {
if (errcode == SQL_SUCCESS)
return;
if(errcode == SQL_ERROR) {
int ret;
long diagCount=0;
short length=0;
SQLCHAR state[10] = "";
SQLCHAR message[200] = "";
long native = 0;
if(hstmt != 0) {
ret = SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_NUMBER, &diagCount, SQL_IS_INTEGER, 0);
for(long i = 0; i < diagCount; i++) {
ret = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, (SQLCHAR*)state, &native, (SQLCHAR*)message, 200, &length);
ndbout_c("GetDiagRec: Message : %s ", message);
}
}
}
if(errcode != SQL_SUCCESS) {
ndbout_c("Message: %s", msg);
switch(errcode) {
case SQL_SUCCESS_WITH_INFO:
ndbout_c("SQL_SUCCESS_WITH_INFO");
break;
case SQL_STILL_EXECUTING:
ndbout_c("SQL_STILL_EXECUTING");
break;
case SQL_ERROR:
ndbout_c("SQL_ERROR");
break;
case SQL_INVALID_HANDLE:
ndbout_c("SQL_INVALID_HANDLE");
break;
default:
ndbout_c("Some other error");
}
exit(1);
}
}
/*********************************************************************
* FUNCTION: usage
*
* DESCRIPTION: This function prints a usage message describing
* the command line options of the program.
*
* PARAMETERS: char* prog full program path name
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
static void usage(char *prog)
{
char *progname;
/* Get the name of the program (sans path). */
#ifdef WIN32
progname = strrchr(prog, '\\');
#else
progname = strrchr(prog, '/');
#endif
if (progname == 0)
progname = prog;
else
++progname;
/* Print the usage message */
fprintf(stderr,
"Usage:\t%s [-h] [-help] [-V] [-connStr <string>] [-v <level>]\n"
"\t\t[-xact <xacts>] [-scale <scale>] [-tabs] [-s <statfile>]\n\n"
" -h Prints this message and exits.\n"
" -help Same as -h.\n"
" -V Prints version number and exits.\n"
" -connStr <string> Specifies an ODBC connection string to replace the\n"
" default DSN for the program. The default is\n"
" \"DSN=TpcbData<version>;OverWrite=1\".\n"
" -v <level> Verbose level\n"
" 0 = errors only\n"
" 1 = results only\n"
" 2 = results and some status messages (default)\n"
" 3 = all messages\n"
" -xact <xacts> Specifies the number of transactions to be run\n"
" The default is 25000 transactions.\n"
" -scale <scale> Specifies a scale factor which determines the\n"
" number of branches (scale), tellers (scale x 10),\n"
" accounts (scale x 10000) and non-local accounts\n"
" ((scale-1) x 10000. The default scale factor is 2.\n"
" -tabs Specifies that the output be a tab-separated\n"
" format suitable for import into a spreadsheet.\n"
" Results only go to stdout; status and other\n"
" messages go to stderr.\n"
" -s <statfile> Prints individual transaction times to <statfile>.\n",
progname);
}
/*********************************************************************
*
* FUNCTION: parse_args
*
* DESCRIPTION: This function parses the command line arguments
* passed to main(), setting the appropriate global
* variables and issuing a usage message for
* invalid arguments.
*
* PARAMETERS: int argc # of arguments from main()
* char *argv[] arguments from main()
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
parse_args(int argc, char *argv[])
{
int i = 1;
*szConnStrIn = 0;
while (i < argc) {
if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") ) {
usage(argv[0]);
app_exit(0);
}
/*
if (!strcmp(argv[i], "-V")) {
printf("%s\n", TTVERSION_STRING);
app_exit(0);
}
*/
if (strcmp(argv[i], "-s") == 0) {
if (argc < i+2 ) {
usage(argv[0]);
app_exit(1);
}
if (sscanf(argv[i+1], "%s", statFile) == 0) {
usage(argv[0]);
app_exit(1);
}
printXactTimes = 1;
i += 2;
}
else if (!strcmp(argv[i], "-connStr")) {
if (argc < i+2 ) {
usage(argv[0]);
app_exit(1);
}
strcpy(szConnStrIn, argv[i+1]);
i += 2;
continue;
}
else if (strcmp("-v", argv[i]) == 0) {
if (argc < i+2 ) {
usage(argv[0]);
app_exit(1);
}
if (sscanf(argv[i+1], "%d", &verbose) == -1 ||
verbose < 0 || verbose > 3) {
fprintf(stderr, "-v flag requires an integer parameter (0-3)\n");
usage(argv[0]);
app_exit(1);
}
i += 2;
}
else if (strcmp("-xact",argv[i]) == 0) {
if (argc < i+2 ) {
usage(argv[0]);
app_exit(1);
}
if (sscanf(argv[i+1], "%" PTRINT_FMT, &numXacts) == -1 || numXacts < 0) {
fprintf(stderr, "-xact flag requires a non-negative integer argument\n");
usage(argv[0]);
app_exit(1);
}
i += 2;
}
else if (strcmp("-scale",argv[i]) == 0) {
if (argc < i+2 ) {
usage(argv[0]);
app_exit(1);
}
if (sscanf(argv[i+1], "%d", &scaleFactor) == -1 || scaleFactor < 1) {
fprintf(stderr, "-scale flag requires an integer argument >= 1\n");
usage(argv[0]);
app_exit(1);
}
/* Calculate tuple sizes */
numBranchTups = NumBranches * scaleFactor;
numTellerTups = TellersPerBranch * scaleFactor;
numAccountTups = AccountsPerBranch * scaleFactor;
numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
i += 2;
}
else if (strcmp("-tabs",argv[i]) == 0) {
tabFlag = 1;
statusfp = stderr;
i += 1;
}
else {
usage(argv[0]);
app_exit(1);
}
}
}
/*********************************************************************
*
* FUNCTION: doImmed
*
* DESCRIPTION: This function executes and frees the specified
* statement. It is used as a direct means to
* create the tables used by this benchmark,
*
* PARAMETERS: SQLHDBC hdbc SQL Connection handle
* SQLHSTMT hs SQL Statement handle
* char* cmd SQL Statement text
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
doImmed(SQLHDBC hdbc, SQLHSTMT hs, char* cmd)
{
SQLRETURN rc;
/* Execute the command */
rc = SQLExecDirect(hs, (SQLCHAR *) cmd, SQL_NTS);
handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
"Error executing statement", __FILE__, __LINE__);
/* Close associated cursor and drop pending results */
rc = SQLFreeStmt(hs, SQL_CLOSE);
handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
"closing statement handle",
__FILE__, __LINE__);
}
/*********************************************************************
*
* FUNCTION: main
*
* DESCRIPTION: This is the main function of the tpcb benchmark.
* It connects to an ODBC data source, creates and
* populates tables, updates the tables in a user-
* specified number of transactions and reports on
* on the transaction times.
*
* PARAMETERS: int argc # of command line arguments
* char *argv[] command line arguments
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
int
main(int argc, char *argv[])
{
/* variables used for setting up the tables */
char cmdStr[1024];
char errstr[4096];
/* variables used during transactions */
int accountNum;
int tellerNum;
int branchNum;
int timeStamp;
double delta;
unsigned int lrand;
unsigned short *srands, localLimit;
int lp64;
/* variables used for timing and statistics */
int warmup;
double kernel, user, real;
ttThreadTimes startRes, endRes;
ttWallClockTime startT, endT;
ttWallClockTime** rtStart;
ttWallClockTime** rtEnd;
double** resTime;
double maxTime, totTime;
int i;
int j;
int numLocalXacts=0, numRemoteXacts=0;
/* variables for ODBC */
SQLHDBC hdbc;
SQLHSTMT hstmt;
SQLHSTMT txstmt[NumXactStmts];
SQLRETURN rc;
char DBMSName[32];
char DBMSVersion[32];
int databaseSize;
int fThreadTime = 1;
#ifdef WIN32
OSVERSIONINFO sysInfo;
sysInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
GetVersionEx (&sysInfo);
/* GetThreadTimes is not supported on 95/98. Hence,
we do not support Resource/User/System times */
if (sysInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
fThreadTime = 0;
#endif
#if defined(TTCLIENTSERVER) && defined(__hpux) && !defined(__LP64__)
/* HP requires this for C main programs that call aC++ shared libs */
_main();
#endif /* hpux32 */
/* Set up default signal handlers */
#ifndef NDB
/* StopRequestClear();
if (HandleSignals() != 0) {
err_msg0("Unable to set signal handlers\n");
return 1;
}
*/
#endif
/* set IO mode for demo */
/* set_io_mode(); */
/* initialize the file for status messages */
statusfp = stdout;
/* set variable for 8-byte longs */
lp64 = (sizeof(lrand) == 8);
/* set the default tuple sizes */
numBranchTups = NumBranches * scaleFactor;
numTellerTups = TellersPerBranch * scaleFactor;
numAccountTups = AccountsPerBranch * scaleFactor;
numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
/* parse the command arguments */
parse_args(argc, argv);
/* allocate the transaction-based variables */
rtStart = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
if (!rtStart) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
for (i = 0; i < numXacts; i++) {
rtStart[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
if (!rtStart[i]) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
}
rtEnd = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
if (!rtEnd) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
for (i = 0; i < numXacts; i++) {
rtEnd[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
if (!rtEnd[i]) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
}
resTime = (double**) malloc(numXacts * sizeof(double*));
if (!resTime) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
for (i = 0; i < numXacts; i++) {
resTime[i] = (double*) malloc(sizeof(double));
if (!resTime[i]) {
err_msg0("Cannot allocate the transaction timing structures");
app_exit(1);
}
}
/* ODBC initialization */
rc = SQLAllocEnv(&henv);
if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
/* error occurred -- don't bother calling handle_errors, since handle
* is not valid so SQLError won't work */
err_msg3("ERROR in %s, line %d: %s\n",
__FILE__, __LINE__, "allocating an environment handle");
app_exit(1);
}
SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
/* call this in case of warning */
handle_errors(NULL, NULL, rc, NO_EXIT,
"allocating execution environment",
__FILE__, __LINE__);
rc = SQLAllocConnect(henv, &hdbc);
handle_errors(NULL, NULL, rc, ERROR_EXIT,
"allocating connection handle",
__FILE__, __LINE__);
/* Connect to data store */
status_msg0("Connecting to the data source...\n");
/* Set up the connection options if not specified on the command line
* (default to TimesTen settings).
*/
if ( !*szConnStrIn ) {
/* Running the benchmark with a scale factor creates (scale) branches,
* (scale x 10) tellers, (scale x 10000) accounts and ((scale-1) x 10000)
* non-local accounts. The size of the table rows are branches (141)
* tellers (141) and accounts (141). Therefore the data size requirements
* of this benchmark is:
* size ~= 141 * ((scale * 20011) - 10000) (bytes)
*
* Multiply data size by 20% to account for additional DB overhead (e.g.
* indexes), and round up the nearest 10Mb for safety.
*/
int est_size = (int) (3.6 * scaleFactor + 10.0);
est_size = est_size - (est_size % 10);
sprintf(szConnStrIn,"OverWrite=1;PermSize=%d;%s",
est_size, DSNNAME);
status_msg0("Connecting to the data source... %s \n", szConnStrIn);
}
rc = SQLDriverConnect(hdbc, NULL, (SQLCHAR *) szConnStrIn, SQL_NTS,
NULL, 0, NULL,
SQL_DRIVER_NOPROMPT);
status_msg0("Connected to the data source...\n");
sprintf(errstr, "connecting to driver (connect string %s)\n",
szConnStrIn);
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
errstr, __FILE__, __LINE__);
/* Turn auto-commit off */
rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
"switching off the AUTO_COMMIT option",
__FILE__, __LINE__);
/* Allocate a statement handle */
rc = SQLAllocStmt(hdbc, &hstmt);
handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
"allocating a statement handle",
__FILE__, __LINE__);
/* (Implicit) Transaction begin */
/* Determine the DBMS Type*/
DBMSName[0] = '\0';
rc = SQLGetInfo(hdbc, SQL_DBMS_NAME, (PTR) &DBMSName,
sizeof(DBMSName), NULL);
rc = SQLGetInfo(hdbc, SQL_DRIVER_VER, (PTR) &DBMSVersion,
sizeof(DBMSVersion), NULL);
if (strcmp(DBMSName, "TimesTen") == 0)
DBMSType = DBMS_TIMESTEN;
else if (strcmp(DBMSName, "Microsoft SQL Server") == 0)
DBMSType = DBMS_MSSQL;
else DBMSType = DBMS_UNKNOWN;
/* if not TimesTen: delete (if it exists), create & use the new database */
if (DBMSType != DBMS_TIMESTEN) {
status_msg0("Deleting the database...\n");
rc = SQLExecDirect(hstmt, (SQLCHAR *) DatabaseDropStmt, SQL_NTS);
/* estimate database size, size = data space + log space
* data space = (#tuples)/(tuples per page) * 2K bytes/page
* tuples per page = useable page size / row size (no index) = 2016/(96+2)
* log space = #transactions * average log size for the program transaction mix
* database size is in MB
*/
databaseSize = (int) ceil((((numBranchTups + numTellerTups + numAccountTups)/
(2016/98)) * 2048 + (numXacts * 600)) / 1000000.0);
status_msg1("Creating the database (%dMB)...\n", databaseSize);
#ifndef NDB
sprintf(cmdStr, DatabaseCreateStmt, databaseSize);
doImmed(hdbc, hstmt, cmdStr);
strcpy(cmdStr, DatabaseUseStmt);
doImmed(hdbc, hstmt, cmdStr);
#endif
}
status_msg2("Connected to '%s' version '%s'...\n", DBMSName, DBMSVersion);
/* create branches table */
status_msg0("Creating tasddbles...\n");
#ifndef NDB
if (DBMSType == DBMS_TIMESTEN)
sprintf(cmdStr, TTBranchCrTblStmt, numBranchTups/TuplesPerPage + 1);
else
#endif
sprintf(cmdStr, BranchCrTblStmt);
doImmed(hdbc, hstmt, cmdStr);
/* create tellers table */
#ifndef NDB
if (DBMSType == DBMS_TIMESTEN)
sprintf(cmdStr, TTTellerCrTblStmt, numTellerTups/TuplesPerPage + 1);
else
#endif
sprintf(cmdStr, TellerCrTblStmt);
doImmed(hdbc, hstmt, cmdStr);
/* create accounts table */
#ifndef NDB
if (DBMSType == DBMS_TIMESTEN)
sprintf(cmdStr, TTAccountCrTblStmt, numAccountTups/TuplesPerPage + 1);
else
#endif
sprintf(cmdStr, AccountCrTblStmt);
doImmed(hdbc, hstmt, cmdStr);
/* create History table */
doImmed(hdbc, hstmt, HistoryCrTblStmt);
/* lock the database during population */
#ifndef NDB
if ( DBMSType == DBMS_TIMESTEN ) {
rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('DS')", SQL_NTS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"specifying dbs lock usage",
__FILE__, __LINE__);
/* make sure dbs lock take effect in next transaction */
rc = SQLTransact(henv,hdbc,SQL_COMMIT);
if ( rc != SQL_SUCCESS) {
handle_errors(hdbc, SQL_NULL_HSTMT, rc, ERROR_EXIT,
"committing transaction",
__FILE__, __LINE__);
}
}
#endif
/* populate branches table */
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[0], SQL_NTS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"preparing statement",
__FILE__, __LINE__);
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum, NULL);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
status_msg1("Populating branches table (%" PTRINT_FMT " rows)...\n",
numBranchTups);
for (i=0; i<numBranchTups; i++) {
branchNum = i;
rc = SQLExecute(hstmt);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"Error executing statement",
__FILE__, __LINE__);
}
/* Reset all bind-parameters for the statement handle. */
rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"resetting parms on statement handle",
__FILE__, __LINE__);
/* populate tellers table */
status_msg1("Populating tellers table (%" PTRINT_FMT " rows)...\n",
numTellerTups);
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[1], SQL_NTS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"preparing statement",
__FILE__, __LINE__);
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
10, 0, &tellerNum, sizeof tellerNum, NULL);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
10, 0, &branchNum, sizeof branchNum, NULL);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
for (i=0; i<numTellerTups; i++) {
tellerNum = i;
branchNum = i/TellersPerBranch;
rc = SQLExecute(hstmt);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"Error executing statement",
__FILE__, __LINE__);
}
/* Reset all bind-parameters for the statement handle. */
rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"resetting parms on statement handle",
__FILE__, __LINE__);
/* populate accounts table */
status_msg1("Populating accounts table (%" PTRINT_FMT " rows)...\n",
numAccountTups);
rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[2], SQL_NTS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"preparing statement",
__FILE__, __LINE__);
rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
10, 0, &accountNum, sizeof accountNum, NULL);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
10, 0, &branchNum, sizeof branchNum, NULL);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
for (i=0; i<numAccountTups; i++) {
accountNum = i;
branchNum = i/AccountsPerBranch;
rc = SQLExecute(hstmt);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"Error executing statement",
__FILE__, __LINE__);
}
status_msg0("Commit...\n");
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
status_msg0("Commit done...\n");
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
"committing transaction",
__FILE__, __LINE__);
/* compile SQL statements of transaction */
status_msg0("Compiling statements of transaction...\n");
for (i=0; i<NumXactStmts; i++) {
#ifndef NDB
rc = SQLAllocStmt(hdbc, &txstmt[i]);
handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
"allocating a statement handle",
__FILE__, __LINE__);
#else
rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &txstmt[i]);
handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
"allocating a statement handle",
__FILE__, __LINE__);
#endif
rc = SQLPrepare(txstmt[i], (SQLCHAR *) tpcbXactStmt[i], SQL_NTS);
handle_errors(hdbc, txstmt[i], rc, ABORT_DISCONNECT_EXIT,
"preparing statement",
__FILE__, __LINE__);
}
/* unuse dbs lock */
#ifndef NDB
if ( DBMSType == DBMS_TIMESTEN ) {
rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('Row')", SQL_NTS);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"specifying row lock usage",
__FILE__, __LINE__);
}
#endif
/* commit transaction */
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
"committing transaction",
__FILE__, __LINE__);
/* Initialize random seed and timers */
srand48(SeedVal);
localLimit = (unsigned short)((1<<16) * 0.85);
/* Initialize parameter lists for each of the transactions */
rc = SQLBindParameter(txstmt[0], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[0], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
NULL);
handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[1], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
NULL);
handle_errors(hdbc, txstmt[1], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[2], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[2], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
NULL);
handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[3], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[3], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
NULL);
handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[4], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
NULL);
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[4], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
NULL);
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[4], 3, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
NULL);
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[4], 4, SQL_PARAM_INPUT, SQL_C_DOUBLE,
SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
rc = SQLBindParameter(txstmt[4], 5, SQL_PARAM_INPUT, SQL_C_SLONG,
SQL_INTEGER, 10, 0, &timeStamp, sizeof timeStamp,
NULL);
handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
"binding parameter",
__FILE__, __LINE__);
/* Execute transaction loop.
* Do it twice, once briefly as a warm-up. */
for (warmup = 1; warmup >= 0; warmup--) {
int max_i = (warmup ? numXacts/10 : numXacts);
/* Execute tpcb transaction max_i times.*/
if (warmup) {
status_msg1("\nWarming up with %d tpcb transactions...\n", max_i);
}
else {
status_msg1("Executing and timing %d tpcb transactions...\n", max_i);
}
ttGetWallClockTime(&startT);
ttGetThreadTimes(&startRes);
for (i = 0; i < max_i; i++) {
lrand = lrand48();
srands = (unsigned short *)(&lrand);
if (lp64) srands += 2; /* skip high half -- all zero */
/* randomly choose a teller */
tellerNum = srands[0] % numTellerTups;
/* compute branch */
branchNum = (tellerNum / TellersPerBranch);
/* randomly choose an account */
if (srands[1] < localLimit || numBranchTups == 1) {
/* choose account local to selected branch */
accountNum = branchNum * AccountsPerBranch +
(lrand48() % AccountsPerBranch);
++numLocalXacts;
}
else {
/* choose account not local to selected branch */
/* first select account in range [0,numNonLocalAccountTups) */
accountNum = lrand48() % numNonLocalAccountTups;
/* if branch number of selected account is at least as big
* as local branch number, then increment account number
* by AccountsPerBranch to skip over local accounts
*/
if ((accountNum/AccountsPerBranch) >= branchNum)
accountNum += AccountsPerBranch;
++numRemoteXacts;
}
/* select delta amount, -999,999 to +999,999 */
delta = ((lrand48() % 1999999) - 999999);
/* begin timing the "residence time" */
ttGetWallClockTime(rtStart[i]);
for ( j = 0; j < NumXactStmts - 2; j++) {
rc = SQLExecute(txstmt[j]);
handle_errors(hdbc, txstmt[j], rc, ABORT_DISCONNECT_EXIT,
"Error executing statement1",
__FILE__, __LINE__);
/* Close the handle after the SELECT statement
* (txstmt[1]) for non TimesTen DBMS' */
if ((DBMSType != DBMS_TIMESTEN) && (j == 1)) {
SQLFreeStmt(txstmt[1], SQL_CLOSE);
}
}
/* note that time must be taken within the */
timeStamp = time(NULL);
rc = SQLExecute(txstmt[NumXactStmts - 1]);
handle_errors(hdbc, txstmt[NumXactStmts - 1], rc,
ABORT_DISCONNECT_EXIT, "Error executing statement2",
__FILE__, __LINE__);
rc = SQLTransact(henv, hdbc, SQL_COMMIT);
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
"Error committing transaction",
__FILE__, __LINE__);
ttGetWallClockTime(rtEnd[i]);
} /* end fortransaction loop */
ttGetThreadTimes(&endRes);
ttGetWallClockTime(&endT);
ttCalcElapsedThreadTimes(&startRes, &endRes, &kernel, &user);
ttCalcElapsedWallClockTime(&startT, &endT, &real);
if (warmup) {
if (!tabFlag) {
if (verbose) {
if (fThreadTime) {
out_msg0(" time user system\n");
out_msg3("Warmup time (sec): %12.3f %12.3f %12.3f\n\n",
real/1000.0, user, kernel);
} else {
out_msg1("Warmup time (sec): %12.3f\n\n", real/1000.0);
}
}
} else {
if (verbose) {
if (fThreadTime) {
out_msg0("\ttime\tuser\tsystem\n");
out_msg3("Warmup time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
real/1000.0, user, kernel);
} else {
out_msg1("Warmup time (sec):\t%12.3f\n", real/1000.0);
}
}
}
}
}
status_msg0("\nExecution completed...\n");
/* Compute and report timing statistics */
maxTime = 0.0;
totTime = 0.0;
for (i = 0; i < numXacts; i++) {
ttCalcElapsedWallClockTime(rtStart[i], rtEnd[i], resTime[i]);
totTime += *(resTime[i]);
if (*(resTime[i]) > maxTime) maxTime = *(resTime[i]);
}
if (!tabFlag) {
if (verbose) {
if (fThreadTime) {
out_msg0(" time user system\n");
out_msg3("Total time (sec): %12.3f %12.3f %12.3f\n",
real/1000.0, user, kernel);
} else {
out_msg1("Total time (sec): %12.3f\n", real/1000.0);
}
}
if (verbose)
out_msg1("\nAverage transaction time (msec):%12.3f\n",
totTime/numXacts);
if (verbose)
out_msg1("Maximum transaction time (msec):%12.3f\n", maxTime);
if (verbose)
out_msg1("\nLocal transactions: %7" PTRINT_FMT "\n", numLocalXacts);
if (verbose)
out_msg1("Remote transactions: %7" PTRINT_FMT "\n", numRemoteXacts);
} else {
if (verbose) {
if (fThreadTime) {
out_msg0("\ttime\tuser\tsystem\n");
out_msg3("Total time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
real/1000.0, user, kernel);
} else {
out_msg1("Total time (sec):\t%12.3f\n", real/1000.0);
}
}
if (verbose)
out_msg1("\nAverage transaction time (msec):\t%12.3f\n",
totTime/numXacts);
if (verbose)
out_msg1("Maximum transaction time (msec):\t%12.3f\n", maxTime);
if (verbose)
out_msg1("Local transactions:\t%7" PTRINT_FMT "\n", numLocalXacts);
if (verbose)
out_msg1("Remote transactions:\t%7" PTRINT_FMT "\n", numRemoteXacts);
}
/* If the statfile option is selected, print each transaction's time */
if (printXactTimes) {
FILE * fp;
if ( (fp = fopen (statFile, "w")) == NULL ) {
err_msg1("Unable to open stat file %s for writing\n\n", statFile);
} else {
for (int i = 0; i < numXacts; i++)
fprintf(fp,"%6d: %12.3f\n", i, *(resTime[i]));
fclose(fp);
}
}
/* Disconnect and return */
rc = SQLFreeStmt(hstmt, SQL_DROP);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"dropping the statement handle",
__FILE__, __LINE__);
for (int i=0; i<NumXactStmts; i++) {
rc = SQLFreeStmt(txstmt[i], SQL_DROP);
handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
"dropping the statement handle",
__FILE__, __LINE__);
}
if (verbose >= VERBOSE_DFLT)
status_msg0("Disconnecting from the data source...\n");
rc = SQLDisconnect(hdbc);
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
"disconnecting",
__FILE__, __LINE__);
rc = SQLFreeConnect(hdbc);
handle_errors(hdbc, NULL, rc, ERROR_EXIT,
"freeing connection handle",
__FILE__, __LINE__);
rc = SQLFreeEnv(henv);
handle_errors(NULL, NULL, rc, ERROR_EXIT,
"freeing environment handle",
__FILE__, __LINE__);
app_exit(0);
return 0;
}
/* Emacs variable settings */
/* Local Variables: */
/* tab-width:8 */
/* indent-tabs-mode:nil */
/* c-basic-offset:2 */
/* End: */
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
static const volatile char cvsid[] = "$Id: ttTime.c,v 1.1 2003/09/23 12:43:46 johan Exp $";
/*
* $Revision: 1.1 $
* (c) Copyright 1996-2003, TimesTen, Inc.
* All rights reserved.
*
*/
/* Contains functions for performing elapsed-time calculations
in a portable manner */
#include "ttTime.h"
#ifdef WIN32
#include <stdio.h>
#include <mapiutil.h>
/*------------*/
/* NT VERSION */
/*------------*/
/*********************************************************************
*
* FUNCTION: ttGetThreadTimes
*
* DESCRIPTION: This function sets the supplied parameter's
* user and kernel time for the current thread.
*
* PARAMETERS: ttThreadTimes* timesP thread time structure
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttGetThreadTimes(ttThreadTimes* timesP)
{
BOOL rc;
HANDLE curThread;
FILETIME creationTime;
FILETIME exitTime;
FILETIME kTime;
FILETIME uTime;
memset (&kTime, 0, sizeof (FILETIME));
memset (&uTime, 0, sizeof (FILETIME));
curThread = GetCurrentThread();
rc = GetThreadTimes(curThread,
&creationTime,
&exitTime,
&kTime,
&uTime);
timesP->kernelTime = kTime;
timesP->userTime = uTime;
}
/*********************************************************************
*
* FUNCTION: ttCalcElapsedThreadTimes
*
* DESCRIPTION: This function calculates the user and kernel
* time deltas.
*
* PARAMETERS: ttThreadTimes* beforeP beginning timestamp (IN)
* ttThreadTimes* afterP ending timestamp (IN)
* double* kernelDeltaP kernel time delta (OUT)
* double* userDeltaP user time delta (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
ttThreadTimes* afterP,
double* kernelDeltaP,
double* userDeltaP)
{
static const double secPerHi = (double) 4.294967296; /* 2**32 * 10**-9 */
FILETIME *before, *after;
before = &beforeP->kernelTime;
after = &afterP->kernelTime;
*kernelDeltaP = (double) ((after->dwHighDateTime - before->dwHighDateTime) * secPerHi
+ (after->dwLowDateTime - before->dwLowDateTime) * 100e-9);
before = &beforeP->userTime;
after = &afterP->userTime;
*userDeltaP = (double) ((after->dwHighDateTime - before->dwHighDateTime) * secPerHi
+ (after->dwLowDateTime - before->dwLowDateTime) * 100e-9);
}
/*********************************************************************
*
* FUNCTION: ttGetWallClockTime
*
* DESCRIPTION: This function gets the current wall-clock time.
*
* PARAMETERS: ttWallClockTime* timeP tms time structure (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttGetWallClockTime(ttWallClockTime* timeP)
{
LARGE_INTEGER frequency;
if ( QueryPerformanceFrequency(&frequency) ) {
QueryPerformanceCounter(&(timeP->time64));
}
else {
_ftime(&(timeP->notSoLargeTime));
}
}
/*********************************************************************
*
* FUNCTION: ttCalcElapsedWallClockTime
*
* DESCRIPTION: This function calculates the elapsed wall-clock
* time in msec.
*
* PARAMETERS: ttWallClockTime* beforeP starting timestamp
* ttWallClockTime* afterP ending timestamp
* double* nmillisecondsP elapsed time (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
ttWallClockTime* afterP,
double* nmillisecondsP)
{
LARGE_INTEGER frequency;
if ( QueryPerformanceFrequency(&frequency) ) {
*nmillisecondsP = 1000 * ((double) (afterP->time64.QuadPart
- beforeP->time64.QuadPart))
/ frequency.QuadPart;
}
else {
double start;
double end;
start = (double) beforeP->notSoLargeTime.time * 1000. +
(double) beforeP->notSoLargeTime.millitm;
end = (double) afterP->notSoLargeTime.time * 1000. +
(double) afterP->notSoLargeTime.millitm;
*nmillisecondsP = (double) (end - start);
}
}
#elif defined (RTSYS_VXWORKS)
/*-----------------*/
/* VxWorks VERSION */
/*-----------------*/
/*
* The TimeBase registers have a period of 60ns, i.e.
* 0.00000006 or (6e-8) seconds.
*/
#define TIMER_MSEC_PER_CYC (6e-5)
void
ttGetWallClockTime(ttWallClockTime* timeP)
{
vxTimeBaseGet(&timeP->sep.upper32, &timeP->sep.lower32);
}
void
ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
ttWallClockTime* afterP,
double* nmillisecondsP)
{
*nmillisecondsP = (double)(afterP->val - beforeP->val) * TIMER_MSEC_PER_CYC;
}
#else
/*--------------*/
/* UNIX VERSION */
/*--------------*/
#include <unistd.h>
/*********************************************************************
*
* FUNCTION: ttGetThreadTimes
*
* DESCRIPTION: This function sets the supplied parameter's
* tms structure.
*
* PARAMETERS: ttThreadTimes* timesP tms time structure
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
#ifdef SB_P_OS_CHORUS
void ttGetThreadTimes(ttThreadTimes* timesP)
{
KnCap actorCap;
if (acap (agetId(), &actorCap) == -1) {
timesP->ins.tmSec = 0;
timesP->ins.tmNSec = 0;
timesP->ext.tmSec = 0;
timesP->ext.tmNSec = 0;
}
else {
(void) threadTimes (&actorCap, K_ALLACTORTHREADS,
&timesP->ins, &timesP->ext);
}
}
#else
void ttGetThreadTimes(ttThreadTimes* timesP)
{
(void) times(timesP);
}
#endif
/*********************************************************************
*
* FUNCTION: ttCalcElapsedThreadTimes
*
* DESCRIPTION: This function calculates the user and kernel
* time deltas.
*
* PARAMETERS: ttThreadTimes* beforeP beginning timestamp (IN)
* ttThreadTimes* afterP ending timestamp (IN)
* double* kernelDeltaP kernel time delta (OUT)
* double* userDeltaP user time delta (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
#ifdef SB_P_OS_CHORUS
void
ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
ttThreadTimes* afterP,
double* kernelDeltaP,
double* userDeltaP)
{
double kernelBefore;
double kernelAfter;
double userBefore;
double userAfter;
kernelBefore = (beforeP->ext.tmSec) + (beforeP->ext.tmNSec / 1e9);
kernelAfter = (afterP->ext.tmSec) + (afterP->ext.tmNSec / 1e9);
*kernelDeltaP = kernelAfter - kernelBefore;
userBefore = (beforeP->ins.tmSec) + (beforeP->ins.tmNSec / 1e9);
userAfter = (afterP->ins.tmSec) + (afterP->ins.tmNSec / 1e9);
*userDeltaP = userAfter - userBefore;
}
#else
void
ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
ttThreadTimes* afterP,
double* kernelDeltaP,
double* userDeltaP)
{
double ticks = (double)sysconf(_SC_CLK_TCK);
*kernelDeltaP = (afterP->tms_stime - beforeP->tms_stime) / ticks;
*userDeltaP = (afterP->tms_utime - beforeP->tms_utime) / ticks;
}
#endif
/*********************************************************************
*
* FUNCTION: ttGetWallClockTime
*
* DESCRIPTION: This function gets the current wall-clock time.
*
* PARAMETERS: ttWallClockTime* timeP tms time structure (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttGetWallClockTime(ttWallClockTime* timeP)
{
gettimeofday(timeP, NULL);
}
/*********************************************************************
*
* FUNCTION: ttCalcElapsedWallClockTime
*
* DESCRIPTION: This function calculates the elapsed wall-clock
* time is msec.
*
* PARAMETERS: ttWallClockTime* beforeP starting timestamp
* ttWallClockTime* afterP ending timestamp
* double* nmillisecondsP elapsed time (OUT)
*
* RETURNS: void
*
* NOTES: NONE
*
*********************************************************************/
void
ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
ttWallClockTime* afterP,
double* nmillisP)
{
*nmillisP = (afterP->tv_sec - beforeP->tv_sec)*1000.0 +
(afterP->tv_usec - beforeP->tv_usec)/1000.0;
}
#endif
/* Emacs variable settings */
/* Local Variables: */
/* tab-width:8 */
/* indent-tabs-mode:nil */
/* c-basic-offset:2 */
/* End: */
/* Copyright (C) 2003 MySQL AB
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
/*
* $Revision: 1.1 $
* (c) Copyright 1996-2003, TimesTen, Inc.
* All rights reserved.
*
*/
#ifndef __TT_TIME
#define __TT_TIME
#ifdef WIN32
#include <windows.h>
#include <sys/types.h>
#include <sys/timeb.h>
typedef struct {
FILETIME kernelTime;
FILETIME userTime;
} ttThreadTimes;
typedef union {
LARGE_INTEGER time64;
struct _timeb notSoLargeTime;
} ttWallClockTime;
#elif defined(RTSYS_VXWORKS)
#define srand48(x) sb_srand48((x))
#define drand48() sb_drand48()
#ifdef SB_P_OS_VXPPC
/* For little-endian switch the lower, upper fields */
typedef union {
struct {
unsigned int upper32;
unsigned int lower32;
} sep;
long long val;
} ttWallClockTime;
/*
* This is a VxWorks private function to read the PPC's 64 bit Time Base
* Register. This is the assembler dump of this function.
001126e4 7cad42e6 mftb r5, TBU
001126e8 7ccc42e6 mftb r6, TBL
001126ec 7ced42e6 mftb r7, TBU
001126f0 7c053800 cmp crf0, 0, r5, r7
001126f4 4082fff0 bc 0x4, 0x2, vxTimeBaseGet
001126f8 90a30000 stw r5, 0x0(r3)
001126fc 90c40000 stw r6, 0x0(r4)
00112700 4e800020 blr
* This is a fine grained timer with a period of 60ns.
*/
void vxTimeBaseGet(unsigned int* pUpper32, unsigned int* pLower32);
#endif /* SB_P_OS_VXPPC */
#elif defined(SB_P_OS_CHORUS)
#include <sys/types.h>
#include <sys/times.h>
#include <sys/time.h>
#include <vtimer/chVtimer.h>
struct chrTimes {
KnTimeVal ins;
KnTimeVal ext;
};
typedef struct chrTimes ttThreadTimes;
typedef struct timeval ttWallClockTime;
#else
/* UNIX version */
#include <sys/times.h>
#include <sys/time.h>
typedef struct tms ttThreadTimes;
typedef struct timeval ttWallClockTime;
#endif /* NT, VxWorks, Chorus, Unix */
#ifndef RTSYS_VXWORKS
void ttGetThreadTimes(ttThreadTimes* timesP);
void ttCalcElapsedThreadTimes(ttThreadTimes* beforeP, ttThreadTimes* afterP,
double* kernelDeltaP, double* userDeltaP);
#endif /* ! VXWORKS */
void ttGetWallClockTime(ttWallClockTime* timeP);
void ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
ttWallClockTime* afterP,
double* nmillisecondsP);
#endif /* __TT_TIME */
/* Emacs variable settings */
/* Local Variables: */
/* tab-width:8 */
/* indent-tabs-mode:nil */
/* c-basic-offset:2 */
/* End: */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment