pax_global_header 0000666 0000000 0000000 00000000064 13332436400 0014510 g ustar 00root root 0000000 0000000 52 comment=2889b2ff7883aa0181d0135b73b0ad1d7b39b345
libocxl-1.1.0/ 0000775 0000000 0000000 00000000000 13332436400 0013143 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/.cproject 0000664 0000000 0000000 00000026201 13332436400 0014756 0 ustar 00root root 0000000 0000000
libocxl-1.1.0/.editorconfig 0000664 0000000 0000000 00000000222 13332436400 0015614 0 ustar 00root root 0000000 0000000 root = true
[*]
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true
indent_style = tab
indent_size = 4
libocxl-1.1.0/.gitignore 0000664 0000000 0000000 00000000155 13332436400 0015134 0 ustar 00root root 0000000 0000000 *~
*.orig
.*.swp
src/libocxl_info.h
obj/*
testobj/*
sampleobj/*
docs
cppcheck.xml
kernel/include/misc/ocxl.h
libocxl-1.1.0/.project 0000664 0000000 0000000 00000001675 13332436400 0014623 0 ustar 00root root 0000000 0000000
libocxl
org.eclipse.cdt.autotools.core.genmakebuilderV2
org.eclipse.cdt.managedbuilder.core.genmakebuilder
clean,full,incremental,
org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder
full,incremental,
org.eclipse.cdt.core.cnature
org.eclipse.cdt.managedbuilder.core.managedBuildNature
org.eclipse.cdt.managedbuilder.core.ScannerConfigNature
org.eclipse.cdt.autotools.core.autotoolsNatureV2
libocxl-1.1.0/.settings/ 0000775 0000000 0000000 00000000000 13332436400 0015061 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/.settings/language.settings.xml 0000664 0000000 0000000 00000004454 13332436400 0021234 0 ustar 00root root 0000000 0000000
libocxl-1.1.0/COPYING 0000664 0000000 0000000 00000026136 13332436400 0014206 0 ustar 00root root 0000000 0000000
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS
APPENDIX: How to apply the Apache License to your work.
To apply the Apache License to your work, attach the following
boilerplate notice, with the fields enclosed by brackets "[]"
replaced with your own identifying information. (Don't include
the brackets!) The text should be enclosed in the appropriate
comment syntax for the file format. We also recommend that a
file or class name and description of purpose be included on the
same "printed page" as the copyright notice for easier
identification within third-party archives.
Copyright [yyyy] [name of copyright owner]
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
libocxl-1.1.0/Changelog.md 0000664 0000000 0000000 00000001024 13332436400 0015351 0 ustar 00root root 0000000 0000000 # 1.1.0
## User facing changes
- Requires Linux headers >= 4.18 to compile
- Add support for POWER9 wake_host_thread/wait (requires a compiler with GNU extensions for inline assembler)
- Generate warnings on ignored return values
- Use opaque structs rather than void pointers for ocxl handles (this should be transparent to callers)
- Verified GCC 4-8 & Clang 3.6.2-6.0.1 produce correct machine code for OpenCAPI, and whitelisted them
- Verify & enforce that we compile with strict ANSI C (2011)
# 1.0.0
- Initial Release
libocxl-1.1.0/Doxyfile-html 0000664 0000000 0000000 00000322200 13332436400 0015612 0 ustar 00root root 0000000 0000000 # Doxyfile 1.8.13
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
# for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = libocxl
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = docs
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.
CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH = src src/include
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = YES
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings.
# Minimum value: 0, maximum value: 99, default value: 0.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
TOC_INCLUDE_HEADINGS = 0
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = YES
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = YES
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = NO
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
# The default value is: system dependent.
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = YES
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = NO
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if ... \endif and \cond
# ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = README.md src/afu.c src/irq.c src/mmio.c src/setup.c src/include/libocxl.h
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
# possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.idl \
*.ddl \
*.odl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.cs \
*.d \
*.php \
*.php4 \
*.php5 \
*.phtml \
*.inc \
*.m \
*.markdown \
*.md \
*.mm \
*.dox \
*.py \
*.pyw \
*.f90 \
*.f95 \
*.f03 \
*.f08 \
*.f \
*.for \
*.tcl \
*.vhd \
*.vhdl \
*.ucf \
*.qsf
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS = *
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
#
#
# where is the value of the INPUT_FILTER tag, and is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE = README.md
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = YES
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = YES
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see http://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = YES
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:SOURCE_BRO
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from http://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use + S
# (what the is depends on the OS and browser, but it is typically
# , /, or both). Inside the search box use the to jump into the search results window, the results can be navigated
# using the . Press to select an item or to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing +. Also here use the
# to select a filter and or to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
# Note that when enabling USE_PDFLATEX this option is only used for generating
# bitmaps for formulas in the HTML output, but not in the Makefile that is
# written to the output directory.
# The default file is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just
# by its name or with the correct syntax as to be used with the LaTeX
# \usepackage command. To get the times font for instance you can specify :
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
# file, i.e. a series of assignments. You only have to provide replacements,
# missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = NO
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = YES
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
# structure of the code including all documentation. Note that this feature is
# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = _ARCH_PPC64 _DOXYGEN_ LIBOCXL_WARN_UNUSED=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED = LIBOCXL_WARN_UNUSED
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of 'which perl').
# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see:
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = NO
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command. Disabling a call graph can be
# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = YES
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command. Disabling a caller graph can be
# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = YES
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
# configuration file for plantuml.
PLANTUML_CFG_FILE =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
libocxl-1.1.0/Doxyfile-man 0000664 0000000 0000000 00000322135 13332436400 0015430 0 ustar 00root root 0000000 0000000 # Doxyfile 1.8.13
# This file describes the settings to be used by the documentation system
# doxygen (www.doxygen.org) for a project.
#
# All text after a double hash (##) is considered a comment and is placed in
# front of the TAG it is preceding.
#
# All text after a single hash (#) is considered a comment and will be ignored.
# The format is:
# TAG = value [value, ...]
# For lists, items can also be appended using:
# TAG += value [value, ...]
# Values that contain spaces should be placed between quotes (\" \").
#---------------------------------------------------------------------------
# Project related configuration options
#---------------------------------------------------------------------------
# This tag specifies the encoding used for all characters in the config file
# that follow. The default is UTF-8 which is also the encoding used for all text
# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv
# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv
# for the list of possible encodings.
# The default value is: UTF-8.
DOXYFILE_ENCODING = UTF-8
# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by
# double-quotes, unless you are using Doxywizard) that should identify the
# project for which the documentation is generated. This name is used in the
# title of most generated pages and in a few other places.
# The default value is: My Project.
PROJECT_NAME = libocxl
# The PROJECT_NUMBER tag can be used to enter a project or revision number. This
# could be handy for archiving the generated documentation or if some version
# control system is used.
PROJECT_NUMBER =
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a
# quick idea about the purpose of the project. Keep the description short.
PROJECT_BRIEF =
# With the PROJECT_LOGO tag one can specify a logo or an icon that is included
# in the documentation. The maximum height of the logo should not exceed 55
# pixels and the maximum width should not exceed 200 pixels. Doxygen will copy
# the logo to the output directory.
PROJECT_LOGO =
# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path
# into which the generated documentation will be written. If a relative path is
# entered, it will be relative to the location where doxygen was started. If
# left blank the current directory will be used.
OUTPUT_DIRECTORY = docs
# If the CREATE_SUBDIRS tag is set to YES then doxygen will create 4096 sub-
# directories (in 2 levels) under the output directory of each output format and
# will distribute the generated files over these directories. Enabling this
# option can be useful when feeding doxygen a huge amount of source files, where
# putting all generated files in the same directory would otherwise causes
# performance problems for the file system.
# The default value is: NO.
CREATE_SUBDIRS = NO
# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII
# characters to appear in the names of generated files. If set to NO, non-ASCII
# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode
# U+3044.
# The default value is: NO.
ALLOW_UNICODE_NAMES = NO
# The OUTPUT_LANGUAGE tag is used to specify the language in which all
# documentation generated by doxygen is written. Doxygen will use this
# information to generate all constant output in the proper language.
# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese,
# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States),
# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian,
# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages),
# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian,
# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian,
# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish,
# Ukrainian and Vietnamese.
# The default value is: English.
OUTPUT_LANGUAGE = English
# If the BRIEF_MEMBER_DESC tag is set to YES, doxygen will include brief member
# descriptions after the members that are listed in the file and class
# documentation (similar to Javadoc). Set to NO to disable this.
# The default value is: YES.
BRIEF_MEMBER_DESC = YES
# If the REPEAT_BRIEF tag is set to YES, doxygen will prepend the brief
# description of a member or function before the detailed description
#
# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the
# brief descriptions will be completely suppressed.
# The default value is: YES.
REPEAT_BRIEF = YES
# This tag implements a quasi-intelligent brief description abbreviator that is
# used to form the text in various listings. Each string in this list, if found
# as the leading text of the brief description, will be stripped from the text
# and the result, after processing the whole list, is used as the annotated
# text. Otherwise, the brief description is used as-is. If left blank, the
# following values are used ($name is automatically replaced with the name of
# the entity):The $name class, The $name widget, The $name file, is, provides,
# specifies, contains, represents, a, an and the.
ABBREVIATE_BRIEF = "The $name class" \
"The $name widget" \
"The $name file" \
is \
provides \
specifies \
contains \
represents \
a \
an \
the
# If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then
# doxygen will generate a detailed section even if there is only a brief
# description.
# The default value is: NO.
ALWAYS_DETAILED_SEC = NO
# If the INLINE_INHERITED_MEMB tag is set to YES, doxygen will show all
# inherited members of a class in the documentation of that class as if those
# members were ordinary class members. Constructors, destructors and assignment
# operators of the base classes will not be shown.
# The default value is: NO.
INLINE_INHERITED_MEMB = NO
# If the FULL_PATH_NAMES tag is set to YES, doxygen will prepend the full path
# before files name in the file list and in the header files. If set to NO the
# shortest path that makes the file name unique will be used
# The default value is: YES.
FULL_PATH_NAMES = NO
# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path.
# Stripping is only done if one of the specified strings matches the left-hand
# part of the path. The tag can be used to show relative paths in the file list.
# If left blank the directory from which doxygen is run is used as the path to
# strip.
#
# Note that you can specify absolute paths here, but also relative paths, which
# will be relative from the directory where doxygen is started.
# This tag requires that the tag FULL_PATH_NAMES is set to YES.
STRIP_FROM_PATH = src src/include
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the
# path mentioned in the documentation of a class, which tells the reader which
# header file to include in order to use a class. If left blank only the name of
# the header file containing the class definition is used. Otherwise one should
# specify the list of include paths that are normally passed to the compiler
# using the -I flag.
STRIP_FROM_INC_PATH =
# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but
# less readable) file names. This can be useful is your file systems doesn't
# support long names like on DOS, Mac, or CD-ROM.
# The default value is: NO.
SHORT_NAMES = NO
# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the
# first line (until the first dot) of a Javadoc-style comment as the brief
# description. If set to NO, the Javadoc-style will behave just like regular Qt-
# style comments (thus requiring an explicit @brief command for a brief
# description.)
# The default value is: NO.
JAVADOC_AUTOBRIEF = YES
# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first
# line (until the first dot) of a Qt-style comment as the brief description. If
# set to NO, the Qt-style will behave just like regular Qt-style comments (thus
# requiring an explicit \brief command for a brief description.)
# The default value is: NO.
QT_AUTOBRIEF = NO
# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a
# multi-line C++ special comment block (i.e. a block of //! or /// comments) as
# a brief description. This used to be the default behavior. The new default is
# to treat a multi-line C++ comment block as a detailed description. Set this
# tag to YES if you prefer the old behavior instead.
#
# Note that setting this tag to YES also means that rational rose comments are
# not recognized any more.
# The default value is: NO.
MULTILINE_CPP_IS_BRIEF = NO
# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the
# documentation from any documented member that it re-implements.
# The default value is: YES.
INHERIT_DOCS = YES
# If the SEPARATE_MEMBER_PAGES tag is set to YES then doxygen will produce a new
# page for each member. If set to NO, the documentation of a member will be part
# of the file/class/namespace that contains it.
# The default value is: NO.
SEPARATE_MEMBER_PAGES = NO
# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen
# uses this value to replace tabs by spaces in code fragments.
# Minimum value: 1, maximum value: 16, default value: 4.
TAB_SIZE = 4
# This tag can be used to specify a number of aliases that act as commands in
# the documentation. An alias has the form:
# name=value
# For example adding
# "sideeffect=@par Side Effects:\n"
# will allow you to put the command \sideeffect (or @sideeffect) in the
# documentation, which will result in a user-defined paragraph with heading
# "Side Effects:". You can put \n's in the value part of an alias to insert
# newlines.
ALIASES =
# This tag can be used to specify a number of word-keyword mappings (TCL only).
# A mapping has the form "name=value". For example adding "class=itcl::class"
# will allow you to use the command class in the itcl::class meaning.
TCL_SUBST =
# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources
# only. Doxygen will then generate output that is more tailored for C. For
# instance, some of the names that are used will be different. The list of all
# members will be omitted, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_FOR_C = YES
# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or
# Python sources only. Doxygen will then generate output that is more tailored
# for that language. For instance, namespaces will be presented as packages,
# qualified scopes will look different, etc.
# The default value is: NO.
OPTIMIZE_OUTPUT_JAVA = NO
# Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran
# sources. Doxygen will then generate output that is tailored for Fortran.
# The default value is: NO.
OPTIMIZE_FOR_FORTRAN = NO
# Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL
# sources. Doxygen will then generate output that is tailored for VHDL.
# The default value is: NO.
OPTIMIZE_OUTPUT_VHDL = NO
# Doxygen selects the parser to use depending on the extension of the files it
# parses. With this tag you can assign which parser to use for a given
# extension. Doxygen has a built-in mapping, but you can override or extend it
# using this tag. The format is ext=language, where ext is a file extension, and
# language is one of the parsers supported by doxygen: IDL, Java, Javascript,
# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran:
# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran:
# Fortran. In the later case the parser tries to guess whether the code is fixed
# or free formatted code, this is the default for Fortran type files), VHDL. For
# instance to make doxygen treat .inc files as Fortran files (default is PHP),
# and .f files as C (default is Fortran), use: inc=Fortran f=C.
#
# Note: For files without extension you can use no_extension as a placeholder.
#
# Note that for custom extensions you also need to set FILE_PATTERNS otherwise
# the files are not read by doxygen.
EXTENSION_MAPPING =
# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments
# according to the Markdown format, which allows for more readable
# documentation. See http://daringfireball.net/projects/markdown/ for details.
# The output of markdown processing is further processed by doxygen, so you can
# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in
# case of backward compatibilities issues.
# The default value is: YES.
MARKDOWN_SUPPORT = YES
# When the TOC_INCLUDE_HEADINGS tag is set to a non-zero value, all headings up
# to that level are automatically included in the table of contents, even if
# they do not have an id attribute.
# Note: This feature currently applies only to Markdown headings.
# Minimum value: 0, maximum value: 99, default value: 0.
# This tag requires that the tag MARKDOWN_SUPPORT is set to YES.
TOC_INCLUDE_HEADINGS = 0
# When enabled doxygen tries to link words that correspond to documented
# classes, or namespaces to their corresponding documentation. Such a link can
# be prevented in individual cases by putting a % sign in front of the word or
# globally by setting AUTOLINK_SUPPORT to NO.
# The default value is: YES.
AUTOLINK_SUPPORT = YES
# If you use STL classes (i.e. std::string, std::vector, etc.) but do not want
# to include (a tag file for) the STL sources as input, then you should set this
# tag to YES in order to let doxygen match functions declarations and
# definitions whose arguments contain STL classes (e.g. func(std::string);
# versus func(std::string) {}). This also make the inheritance and collaboration
# diagrams that involve STL classes more complete and accurate.
# The default value is: NO.
BUILTIN_STL_SUPPORT = NO
# If you use Microsoft's C++/CLI language, you should set this option to YES to
# enable parsing support.
# The default value is: NO.
CPP_CLI_SUPPORT = NO
# Set the SIP_SUPPORT tag to YES if your project consists of sip (see:
# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen
# will parse them like normal C++ but will assume all classes use public instead
# of private inheritance when no explicit protection keyword is present.
# The default value is: NO.
SIP_SUPPORT = NO
# For Microsoft's IDL there are propget and propput attributes to indicate
# getter and setter methods for a property. Setting this option to YES will make
# doxygen to replace the get and set methods by a property in the documentation.
# This will only work if the methods are indeed getting or setting a simple
# type. If this is not the case, or you want to show the methods anyway, you
# should set this option to NO.
# The default value is: YES.
IDL_PROPERTY_SUPPORT = YES
# If member grouping is used in the documentation and the DISTRIBUTE_GROUP_DOC
# tag is set to YES then doxygen will reuse the documentation of the first
# member in the group (if any) for the other members of the group. By default
# all members of a group must be documented explicitly.
# The default value is: NO.
DISTRIBUTE_GROUP_DOC = NO
# If one adds a struct or class to a group and this option is enabled, then also
# any nested class or struct is added to the same group. By default this option
# is disabled and one has to add nested compounds explicitly via \ingroup.
# The default value is: NO.
GROUP_NESTED_COMPOUNDS = NO
# Set the SUBGROUPING tag to YES to allow class member groups of the same type
# (for instance a group of public functions) to be put as a subgroup of that
# type (e.g. under the Public Functions section). Set it to NO to prevent
# subgrouping. Alternatively, this can be done per class using the
# \nosubgrouping command.
# The default value is: YES.
SUBGROUPING = YES
# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions
# are shown inside the group in which they are included (e.g. using \ingroup)
# instead of on a separate page (for HTML and Man pages) or section (for LaTeX
# and RTF).
#
# Note that this feature does not work in combination with
# SEPARATE_MEMBER_PAGES.
# The default value is: NO.
INLINE_GROUPED_CLASSES = NO
# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions
# with only public data fields or simple typedef fields will be shown inline in
# the documentation of the scope in which they are defined (i.e. file,
# namespace, or group documentation), provided this scope is documented. If set
# to NO, structs, classes, and unions are shown on a separate page (for HTML and
# Man pages) or section (for LaTeX and RTF).
# The default value is: NO.
INLINE_SIMPLE_STRUCTS = YES
# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or
# enum is documented as struct, union, or enum with the name of the typedef. So
# typedef struct TypeS {} TypeT, will appear in the documentation as a struct
# with name TypeT. When disabled the typedef will appear as a member of a file,
# namespace, or class. And the struct will be named TypeS. This can typically be
# useful for C code in case the coding convention dictates that all compound
# types are typedef'ed and only the typedef is referenced, never the tag name.
# The default value is: NO.
TYPEDEF_HIDES_STRUCT = NO
# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This
# cache is used to resolve symbols given their name and scope. Since this can be
# an expensive process and often the same symbol appears multiple times in the
# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small
# doxygen will become slower. If the cache is too large, memory is wasted. The
# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range
# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536
# symbols. At the end of a run doxygen will report the cache usage and suggest
# the optimal cache size from a speed point of view.
# Minimum value: 0, maximum value: 9, default value: 0.
LOOKUP_CACHE_SIZE = 0
#---------------------------------------------------------------------------
# Build related configuration options
#---------------------------------------------------------------------------
# If the EXTRACT_ALL tag is set to YES, doxygen will assume all entities in
# documentation are documented, even if no documentation was available. Private
# class members and static file members will be hidden unless the
# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES.
# Note: This will also disable the warnings about undocumented members that are
# normally produced when WARNINGS is set to YES.
# The default value is: NO.
EXTRACT_ALL = YES
# If the EXTRACT_PRIVATE tag is set to YES, all private members of a class will
# be included in the documentation.
# The default value is: NO.
EXTRACT_PRIVATE = NO
# If the EXTRACT_PACKAGE tag is set to YES, all members with package or internal
# scope will be included in the documentation.
# The default value is: NO.
EXTRACT_PACKAGE = NO
# If the EXTRACT_STATIC tag is set to YES, all static members of a file will be
# included in the documentation.
# The default value is: NO.
EXTRACT_STATIC = NO
# If the EXTRACT_LOCAL_CLASSES tag is set to YES, classes (and structs) defined
# locally in source files will be included in the documentation. If set to NO,
# only classes defined in header files are included. Does not have any effect
# for Java sources.
# The default value is: YES.
EXTRACT_LOCAL_CLASSES = YES
# This flag is only useful for Objective-C code. If set to YES, local methods,
# which are defined in the implementation section but not in the interface are
# included in the documentation. If set to NO, only methods in the interface are
# included.
# The default value is: NO.
EXTRACT_LOCAL_METHODS = NO
# If this flag is set to YES, the members of anonymous namespaces will be
# extracted and appear in the documentation as a namespace called
# 'anonymous_namespace{file}', where file will be replaced with the base name of
# the file that contains the anonymous namespace. By default anonymous namespace
# are hidden.
# The default value is: NO.
EXTRACT_ANON_NSPACES = NO
# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all
# undocumented members inside documented classes or files. If set to NO these
# members will be included in the various overviews, but no documentation
# section is generated. This option has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_MEMBERS = YES
# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all
# undocumented classes that are normally visible in the class hierarchy. If set
# to NO, these classes will be included in the various overviews. This option
# has no effect if EXTRACT_ALL is enabled.
# The default value is: NO.
HIDE_UNDOC_CLASSES = NO
# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend
# (class|struct|union) declarations. If set to NO, these declarations will be
# included in the documentation.
# The default value is: NO.
HIDE_FRIEND_COMPOUNDS = NO
# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any
# documentation blocks found inside the body of a function. If set to NO, these
# blocks will be appended to the function's detailed documentation block.
# The default value is: NO.
HIDE_IN_BODY_DOCS = NO
# The INTERNAL_DOCS tag determines if documentation that is typed after a
# \internal command is included. If the tag is set to NO then the documentation
# will be excluded. Set it to YES to include the internal documentation.
# The default value is: NO.
INTERNAL_DOCS = NO
# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file
# names in lower-case letters. If set to YES, upper-case letters are also
# allowed. This is useful if you have classes or files whose names only differ
# in case and if your file system supports case sensitive file names. Windows
# and Mac users are advised to set this option to NO.
# The default value is: system dependent.
CASE_SENSE_NAMES = NO
# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with
# their full class and namespace scopes in the documentation. If set to YES, the
# scope will be hidden.
# The default value is: NO.
HIDE_SCOPE_NAMES = YES
# If the HIDE_COMPOUND_REFERENCE tag is set to NO (default) then doxygen will
# append additional text to a page's title, such as Class Reference. If set to
# YES the compound reference will be hidden.
# The default value is: NO.
HIDE_COMPOUND_REFERENCE= NO
# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of
# the files that are included by a file in the documentation of that file.
# The default value is: YES.
SHOW_INCLUDE_FILES = NO
# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each
# grouped member an include statement to the documentation, telling the reader
# which file to include in order to use the member.
# The default value is: NO.
SHOW_GROUPED_MEMB_INC = NO
# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include
# files with double quotes in the documentation rather than with sharp brackets.
# The default value is: NO.
FORCE_LOCAL_INCLUDES = NO
# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the
# documentation for inline members.
# The default value is: YES.
INLINE_INFO = YES
# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the
# (detailed) documentation of file and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order.
# The default value is: YES.
SORT_MEMBER_DOCS = YES
# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief
# descriptions of file, namespace and class members alphabetically by member
# name. If set to NO, the members will appear in declaration order. Note that
# this will also influence the order of the classes in the class list.
# The default value is: NO.
SORT_BRIEF_DOCS = NO
# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the
# (brief and detailed) documentation of class members so that constructors and
# destructors are listed first. If set to NO the constructors will appear in the
# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS.
# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief
# member documentation.
# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting
# detailed member documentation.
# The default value is: NO.
SORT_MEMBERS_CTORS_1ST = NO
# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy
# of group names into alphabetical order. If set to NO the group names will
# appear in their defined order.
# The default value is: NO.
SORT_GROUP_NAMES = NO
# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by
# fully-qualified names, including namespaces. If set to NO, the class list will
# be sorted only by class name, not including the namespace part.
# Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES.
# Note: This option applies only to the class list, not to the alphabetical
# list.
# The default value is: NO.
SORT_BY_SCOPE_NAME = NO
# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper
# type resolution of all parameters of a function it will reject a match between
# the prototype and the implementation of a member function even if there is
# only one candidate or it is obvious which candidate to choose by doing a
# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still
# accept a match between prototype and implementation in such cases.
# The default value is: NO.
STRICT_PROTO_MATCHING = NO
# The GENERATE_TODOLIST tag can be used to enable (YES) or disable (NO) the todo
# list. This list is created by putting \todo commands in the documentation.
# The default value is: YES.
GENERATE_TODOLIST = YES
# The GENERATE_TESTLIST tag can be used to enable (YES) or disable (NO) the test
# list. This list is created by putting \test commands in the documentation.
# The default value is: YES.
GENERATE_TESTLIST = YES
# The GENERATE_BUGLIST tag can be used to enable (YES) or disable (NO) the bug
# list. This list is created by putting \bug commands in the documentation.
# The default value is: YES.
GENERATE_BUGLIST = YES
# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or disable (NO)
# the deprecated list. This list is created by putting \deprecated commands in
# the documentation.
# The default value is: YES.
GENERATE_DEPRECATEDLIST= YES
# The ENABLED_SECTIONS tag can be used to enable conditional documentation
# sections, marked by \if ... \endif and \cond
# ... \endcond blocks.
ENABLED_SECTIONS =
# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the
# initial value of a variable or macro / define can have for it to appear in the
# documentation. If the initializer consists of more lines than specified here
# it will be hidden. Use a value of 0 to hide initializers completely. The
# appearance of the value of individual variables and macros / defines can be
# controlled using \showinitializer or \hideinitializer command in the
# documentation regardless of this setting.
# Minimum value: 0, maximum value: 10000, default value: 30.
MAX_INITIALIZER_LINES = 30
# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at
# the bottom of the documentation of classes and structs. If set to YES, the
# list will mention the files that were used to generate the documentation.
# The default value is: YES.
SHOW_USED_FILES = YES
# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This
# will remove the Files entry from the Quick Index and from the Folder Tree View
# (if specified).
# The default value is: YES.
SHOW_FILES = YES
# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces
# page. This will remove the Namespaces entry from the Quick Index and from the
# Folder Tree View (if specified).
# The default value is: YES.
SHOW_NAMESPACES = YES
# The FILE_VERSION_FILTER tag can be used to specify a program or script that
# doxygen should invoke to get the current version for each file (typically from
# the version control system). Doxygen will invoke the program by executing (via
# popen()) the command command input-file, where command is the value of the
# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided
# by doxygen. Whatever the program writes to standard output is used as the file
# version. For an example see the documentation.
FILE_VERSION_FILTER =
# The LAYOUT_FILE tag can be used to specify a layout file which will be parsed
# by doxygen. The layout file controls the global structure of the generated
# output files in an output format independent way. To create the layout file
# that represents doxygen's defaults, run doxygen with the -l option. You can
# optionally specify a file name after the option, if omitted DoxygenLayout.xml
# will be used as the name of the layout file.
#
# Note that if you run doxygen from a directory containing a file called
# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE
# tag is left empty.
LAYOUT_FILE =
# The CITE_BIB_FILES tag can be used to specify one or more bib files containing
# the reference definitions. This must be a list of .bib files. The .bib
# extension is automatically appended if omitted. This requires the bibtex tool
# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info.
# For LaTeX the style of the bibliography can be controlled using
# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the
# search path. See also \cite for info how to create references.
CITE_BIB_FILES =
#---------------------------------------------------------------------------
# Configuration options related to warning and progress messages
#---------------------------------------------------------------------------
# The QUIET tag can be used to turn on/off the messages that are generated to
# standard output by doxygen. If QUIET is set to YES this implies that the
# messages are off.
# The default value is: NO.
QUIET = YES
# The WARNINGS tag can be used to turn on/off the warning messages that are
# generated to standard error (stderr) by doxygen. If WARNINGS is set to YES
# this implies that the warnings are on.
#
# Tip: Turn warnings on while writing the documentation.
# The default value is: YES.
WARNINGS = YES
# If the WARN_IF_UNDOCUMENTED tag is set to YES then doxygen will generate
# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag
# will automatically be disabled.
# The default value is: YES.
WARN_IF_UNDOCUMENTED = YES
# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for
# potential errors in the documentation, such as not documenting some parameters
# in a documented function, or documenting parameters that don't exist or using
# markup commands wrongly.
# The default value is: YES.
WARN_IF_DOC_ERROR = YES
# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that
# are documented, but have no documentation for their parameters or return
# value. If set to NO, doxygen will only warn about wrong or incomplete
# parameter documentation, but not about the absence of documentation.
# The default value is: NO.
WARN_NO_PARAMDOC = YES
# If the WARN_AS_ERROR tag is set to YES then doxygen will immediately stop when
# a warning is encountered.
# The default value is: NO.
WARN_AS_ERROR = NO
# The WARN_FORMAT tag determines the format of the warning messages that doxygen
# can produce. The string should contain the $file, $line, and $text tags, which
# will be replaced by the file and line number from which the warning originated
# and the warning text. Optionally the format may contain $version, which will
# be replaced by the version of the file (if it could be obtained via
# FILE_VERSION_FILTER)
# The default value is: $file:$line: $text.
WARN_FORMAT = "$file:$line: $text"
# The WARN_LOGFILE tag can be used to specify a file to which warning and error
# messages should be written. If left blank the output is written to standard
# error (stderr).
WARN_LOGFILE =
#---------------------------------------------------------------------------
# Configuration options related to the input files
#---------------------------------------------------------------------------
# The INPUT tag is used to specify the files and/or directories that contain
# documented source files. You may enter file names like myfile.cpp or
# directories like /usr/src/myproject. Separate the files or directories with
# spaces. See also FILE_PATTERNS and EXTENSION_MAPPING
# Note: If this tag is empty the current directory is searched.
INPUT = src/afu.c src/irq.c src/mmio.c src/setup.c src/include/libocxl.h
# This tag can be used to specify the character encoding of the source files
# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses
# libiconv (or the iconv built into libc) for the transcoding. See the libiconv
# documentation (see: http://www.gnu.org/software/libiconv) for the list of
# possible encodings.
# The default value is: UTF-8.
INPUT_ENCODING = UTF-8
# If the value of the INPUT tag contains directories, you can use the
# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and
# *.h) to filter out the source-files in the directories.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# read by doxygen.
#
# If left blank the following patterns are tested:*.c, *.cc, *.cxx, *.cpp,
# *.c++, *.java, *.ii, *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h,
# *.hh, *.hxx, *.hpp, *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc,
# *.m, *.markdown, *.md, *.mm, *.dox, *.py, *.pyw, *.f90, *.f95, *.f03, *.f08,
# *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf and *.qsf.
FILE_PATTERNS = *.c \
*.cc \
*.cxx \
*.cpp \
*.c++ \
*.java \
*.ii \
*.ixx \
*.ipp \
*.i++ \
*.inl \
*.idl \
*.ddl \
*.odl \
*.h \
*.hh \
*.hxx \
*.hpp \
*.h++ \
*.cs \
*.d \
*.php \
*.php4 \
*.php5 \
*.phtml \
*.inc \
*.m \
*.markdown \
*.md \
*.mm \
*.dox \
*.py \
*.pyw \
*.f90 \
*.f95 \
*.f03 \
*.f08 \
*.f \
*.for \
*.tcl \
*.vhd \
*.vhdl \
*.ucf \
*.qsf
# The RECURSIVE tag can be used to specify whether or not subdirectories should
# be searched for input files as well.
# The default value is: NO.
RECURSIVE = YES
# The EXCLUDE tag can be used to specify files and/or directories that should be
# excluded from the INPUT source files. This way you can easily exclude a
# subdirectory from a directory tree whose root is specified with the INPUT tag.
#
# Note that relative paths are relative to the directory from which doxygen is
# run.
EXCLUDE =
# The EXCLUDE_SYMLINKS tag can be used to select whether or not files or
# directories that are symbolic links (a Unix file system feature) are excluded
# from the input.
# The default value is: NO.
EXCLUDE_SYMLINKS = NO
# If the value of the INPUT tag contains directories, you can use the
# EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude
# certain files from those directories.
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories for example use the pattern */test/*
EXCLUDE_PATTERNS =
# The EXCLUDE_SYMBOLS tag can be used to specify one or more symbol names
# (namespaces, classes, functions, etc.) that should be excluded from the
# output. The symbol name can be a fully qualified name, a word, or if the
# wildcard * is used, a substring. Examples: ANamespace, AClass,
# AClass::ANamespace, ANamespace::*Test
#
# Note that the wildcards are matched against the file with absolute path, so to
# exclude all test directories use the pattern */test/*
EXCLUDE_SYMBOLS =
# The EXAMPLE_PATH tag can be used to specify one or more files or directories
# that contain example code fragments that are included (see the \include
# command).
EXAMPLE_PATH =
# If the value of the EXAMPLE_PATH tag contains directories, you can use the
# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and
# *.h) to filter out the source-files in the directories. If left blank all
# files are included.
EXAMPLE_PATTERNS = *
# If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be
# searched for input files to be used with the \include or \dontinclude commands
# irrespective of the value of the RECURSIVE tag.
# The default value is: NO.
EXAMPLE_RECURSIVE = NO
# The IMAGE_PATH tag can be used to specify one or more files or directories
# that contain images that are to be included in the documentation (see the
# \image command).
IMAGE_PATH =
# The INPUT_FILTER tag can be used to specify a program that doxygen should
# invoke to filter for each input file. Doxygen will invoke the filter program
# by executing (via popen()) the command:
#
#
#
# where is the value of the INPUT_FILTER tag, and is the
# name of an input file. Doxygen will then use the output that the filter
# program writes to standard output. If FILTER_PATTERNS is specified, this tag
# will be ignored.
#
# Note that the filter must not add or remove lines; it is applied before the
# code is scanned, but not when the output code is generated. If lines are added
# or removed, the anchors will not be placed correctly.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
INPUT_FILTER =
# The FILTER_PATTERNS tag can be used to specify filters on a per file pattern
# basis. Doxygen will compare the file name with each pattern and apply the
# filter if there is a match. The filters are a list of the form: pattern=filter
# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how
# filters are used. If the FILTER_PATTERNS tag is empty or if none of the
# patterns match the file name, INPUT_FILTER is applied.
#
# Note that for custom extensions or not directly supported extensions you also
# need to set EXTENSION_MAPPING for the extension otherwise the files are not
# properly processed by doxygen.
FILTER_PATTERNS =
# If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using
# INPUT_FILTER) will also be used to filter the input files that are used for
# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES).
# The default value is: NO.
FILTER_SOURCE_FILES = NO
# The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file
# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and
# it is also possible to disable source filtering for a specific pattern using
# *.ext= (so without naming a filter).
# This tag requires that the tag FILTER_SOURCE_FILES is set to YES.
FILTER_SOURCE_PATTERNS =
# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that
# is part of the input, its contents will be placed on the main page
# (index.html). This can be useful if you have a project on for instance GitHub
# and want to reuse the introduction page also for the doxygen output.
USE_MDFILE_AS_MAINPAGE =
#---------------------------------------------------------------------------
# Configuration options related to source browsing
#---------------------------------------------------------------------------
# If the SOURCE_BROWSER tag is set to YES then a list of source files will be
# generated. Documented entities will be cross-referenced with these sources.
#
# Note: To get rid of all source code in the generated output, make sure that
# also VERBATIM_HEADERS is set to NO.
# The default value is: NO.
SOURCE_BROWSER = NO
# Setting the INLINE_SOURCES tag to YES will include the body of functions,
# classes and enums directly into the documentation.
# The default value is: NO.
INLINE_SOURCES = NO
# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any
# special comment blocks from generated source code fragments. Normal C, C++ and
# Fortran comments will always remain visible.
# The default value is: YES.
STRIP_CODE_COMMENTS = YES
# If the REFERENCED_BY_RELATION tag is set to YES then for each documented
# function all documented functions referencing it will be listed.
# The default value is: NO.
REFERENCED_BY_RELATION = NO
# If the REFERENCES_RELATION tag is set to YES then for each documented function
# all documented entities called/used by that function will be listed.
# The default value is: NO.
REFERENCES_RELATION = NO
# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set
# to YES then the hyperlinks from functions in REFERENCES_RELATION and
# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will
# link to the documentation.
# The default value is: YES.
REFERENCES_LINK_SOURCE = NO
# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the
# source code will show a tooltip with additional information such as prototype,
# brief description and links to the definition and documentation. Since this
# will make the HTML file larger and loading of large files a bit slower, you
# can opt to disable this feature.
# The default value is: YES.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
SOURCE_TOOLTIPS = YES
# If the USE_HTAGS tag is set to YES then the references to source code will
# point to the HTML generated by the htags(1) tool instead of doxygen built-in
# source browser. The htags tool is part of GNU's global source tagging system
# (see http://www.gnu.org/software/global/global.html). You will need version
# 4.8.6 or higher.
#
# To use it do the following:
# - Install the latest version of global
# - Enable SOURCE_BROWSER and USE_HTAGS in the config file
# - Make sure the INPUT points to the root of the source tree
# - Run doxygen as normal
#
# Doxygen will invoke htags (and that will in turn invoke gtags), so these
# tools must be available from the command line (i.e. in the search path).
#
# The result: instead of the source browser generated by doxygen, the links to
# source code will now point to the output of htags.
# The default value is: NO.
# This tag requires that the tag SOURCE_BROWSER is set to YES.
USE_HTAGS = NO
# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a
# verbatim copy of the header file for each class for which an include is
# specified. Set to NO to disable this.
# See also: Section \class.
# The default value is: YES.
VERBATIM_HEADERS = YES
#---------------------------------------------------------------------------
# Configuration options related to the alphabetical class index
#---------------------------------------------------------------------------
# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all
# compounds will be generated. Enable this if the project contains a lot of
# classes, structs, unions or interfaces.
# The default value is: YES.
ALPHABETICAL_INDEX = YES
# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in
# which the alphabetical index list will be split.
# Minimum value: 1, maximum value: 20, default value: 5.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
COLS_IN_ALPHA_INDEX = 5
# In case all classes in a project start with a common prefix, all classes will
# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag
# can be used to specify a prefix (or a list of prefixes) that should be ignored
# while generating the index headers.
# This tag requires that the tag ALPHABETICAL_INDEX is set to YES.
IGNORE_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the HTML output
#---------------------------------------------------------------------------
# If the GENERATE_HTML tag is set to YES, doxygen will generate HTML output
# The default value is: YES.
GENERATE_HTML = NO
# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_OUTPUT = html
# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each
# generated HTML page (for example: .htm, .php, .asp).
# The default value is: .html.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FILE_EXTENSION = .html
# The HTML_HEADER tag can be used to specify a user-defined HTML header file for
# each generated HTML page. If the tag is left blank doxygen will generate a
# standard header.
#
# To get valid HTML the header file that includes any scripts and style sheets
# that doxygen needs, which is dependent on the configuration options used (e.g.
# the setting GENERATE_TREEVIEW). It is highly recommended to start with a
# default header using
# doxygen -w html new_header.html new_footer.html new_stylesheet.css
# YourConfigFile
# and then modify the file new_header.html. See also section "Doxygen usage"
# for information on how to generate the default header that doxygen normally
# uses.
# Note: The header is subject to change so you typically have to regenerate the
# default header when upgrading to a newer version of doxygen. For a description
# of the possible markers and block names see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_HEADER =
# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each
# generated HTML page. If the tag is left blank doxygen will generate a standard
# footer. See HTML_HEADER for more information on how to generate a default
# footer and what special commands can be used inside the footer. See also
# section "Doxygen usage" for information on how to generate the default footer
# that doxygen normally uses.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_FOOTER =
# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style
# sheet that is used by each HTML page. It can be used to fine-tune the look of
# the HTML output. If left blank doxygen will generate a default style sheet.
# See also section "Doxygen usage" for information on how to generate the style
# sheet that doxygen normally uses.
# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as
# it is more robust and this tag (HTML_STYLESHEET) will in the future become
# obsolete.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_STYLESHEET =
# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# cascading style sheets that are included after the standard style sheets
# created by doxygen. Using this option one can overrule certain style aspects.
# This is preferred over using HTML_STYLESHEET since it does not replace the
# standard style sheet and is therefore more robust against future updates.
# Doxygen will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list). For an example see the documentation.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_STYLESHEET =
# The HTML_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the HTML output directory. Note
# that these files will be copied to the base HTML output directory. Use the
# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these
# files. In the HTML_STYLESHEET file, use the file name only. Also note that the
# files will be copied as-is; there are no commands or markers available.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_EXTRA_FILES =
# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen
# will adjust the colors in the style sheet and background images according to
# this color. Hue is specified as an angle on a colorwheel, see
# http://en.wikipedia.org/wiki/Hue for more information. For instance the value
# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300
# purple, and 360 is red again.
# Minimum value: 0, maximum value: 359, default value: 220.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_HUE = 220
# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors
# in the HTML output. For a value of 0 the output will use grayscales only. A
# value of 255 will produce the most vivid colors.
# Minimum value: 0, maximum value: 255, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_SAT = 100
# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the
# luminance component of the colors in the HTML output. Values below 100
# gradually make the output lighter, whereas values above 100 make the output
# darker. The value divided by 100 is the actual gamma applied, so 80 represents
# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not
# change the gamma.
# Minimum value: 40, maximum value: 240, default value: 80.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_COLORSTYLE_GAMMA = 80
# If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML
# page will contain the date and time when the page was generated. Setting this
# to YES can help to show when doxygen was last run and thus if the
# documentation is up to date.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_TIMESTAMP = NO
# If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML
# documentation will contain sections that can be hidden and shown after the
# page has loaded.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_DYNAMIC_SECTIONS = NO
# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries
# shown in the various tree structured indices initially; the user can expand
# and collapse entries dynamically later on. Doxygen will expand the tree to
# such a level that at most the specified number of entries are visible (unless
# a fully collapsed tree already exceeds this amount). So setting the number of
# entries 1 will produce a full collapsed tree by default. 0 is a special value
# representing an infinite number of entries and will result in a full expanded
# tree by default.
# Minimum value: 0, maximum value: 9999, default value: 100.
# This tag requires that the tag GENERATE_HTML is set to YES.
HTML_INDEX_NUM_ENTRIES = 100
# If the GENERATE_DOCSET tag is set to YES, additional index files will be
# generated that can be used as input for Apple's Xcode 3 integrated development
# environment (see: http://developer.apple.com/tools/xcode/), introduced with
# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a
# Makefile in the HTML output directory. Running make will produce the docset in
# that directory and running make install will install the docset in
# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at
# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html
# for more information.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_DOCSET = NO
# This tag determines the name of the docset feed. A documentation feed provides
# an umbrella under which multiple documentation sets from a single provider
# (such as a company or product suite) can be grouped.
# The default value is: Doxygen generated docs.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_FEEDNAME = "Doxygen generated docs"
# This tag specifies a string that should uniquely identify the documentation
# set bundle. This should be a reverse domain-name style string, e.g.
# com.mycompany.MyDocSet. Doxygen will append .docset to the name.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_BUNDLE_ID = org.doxygen.Project
# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify
# the documentation publisher. This should be a reverse domain-name style
# string, e.g. com.mycompany.MyDocSet.documentation.
# The default value is: org.doxygen.Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_ID = org.doxygen.Publisher
# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher.
# The default value is: Publisher.
# This tag requires that the tag GENERATE_DOCSET is set to YES.
DOCSET_PUBLISHER_NAME = Publisher
# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three
# additional HTML index files: index.hhp, index.hhc, and index.hhk. The
# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop
# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on
# Windows.
#
# The HTML Help Workshop contains a compiler that can convert all HTML output
# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML
# files are now used as the Windows 98 help format, and will replace the old
# Windows help format (.hlp) on all Windows platforms in the future. Compressed
# HTML files also contain an index, a table of contents, and you can search for
# words in the documentation. The HTML workshop also contains a viewer for
# compressed HTML files.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_HTMLHELP = NO
# The CHM_FILE tag can be used to specify the file name of the resulting .chm
# file. You can add a path in front of the file if the result should not be
# written to the html output directory.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_FILE =
# The HHC_LOCATION tag can be used to specify the location (absolute path
# including file name) of the HTML help compiler (hhc.exe). If non-empty,
# doxygen will try to run the HTML help compiler on the generated index.hhp.
# The file has to be specified with full path.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
HHC_LOCATION =
# The GENERATE_CHI flag controls if a separate .chi index file is generated
# (YES) or that it should be included in the master .chm file (NO).
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
GENERATE_CHI = NO
# The CHM_INDEX_ENCODING is used to encode HtmlHelp index (hhk), content (hhc)
# and project file content.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
CHM_INDEX_ENCODING =
# The BINARY_TOC flag controls whether a binary table of contents is generated
# (YES) or a normal table of contents (NO) in the .chm file. Furthermore it
# enables the Previous and Next buttons.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
BINARY_TOC = NO
# The TOC_EXPAND flag can be set to YES to add extra items for group members to
# the table of contents of the HTML help documentation and to the tree view.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTMLHELP is set to YES.
TOC_EXPAND = NO
# If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and
# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that
# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help
# (.qch) of the generated HTML documentation.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_QHP = NO
# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify
# the file name of the resulting .qch file. The path specified is relative to
# the HTML output folder.
# This tag requires that the tag GENERATE_QHP is set to YES.
QCH_FILE =
# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help
# Project output. For more information please see Qt Help Project / Namespace
# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace).
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_NAMESPACE = org.doxygen.Project
# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt
# Help Project output. For more information please see Qt Help Project / Virtual
# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual-
# folders).
# The default value is: doc.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_VIRTUAL_FOLDER = doc
# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom
# filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_NAME =
# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the
# custom filter to add. For more information please see Qt Help Project / Custom
# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom-
# filters).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_CUST_FILTER_ATTRS =
# The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this
# project's filter section matches. Qt Help Project / Filter Attributes (see:
# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes).
# This tag requires that the tag GENERATE_QHP is set to YES.
QHP_SECT_FILTER_ATTRS =
# The QHG_LOCATION tag can be used to specify the location of Qt's
# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the
# generated .qhp file.
# This tag requires that the tag GENERATE_QHP is set to YES.
QHG_LOCATION =
# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be
# generated, together with the HTML files, they form an Eclipse help plugin. To
# install this plugin and make it available under the help contents menu in
# Eclipse, the contents of the directory containing the HTML and XML files needs
# to be copied into the plugins directory of eclipse. The name of the directory
# within the plugins directory should be the same as the ECLIPSE_DOC_ID value.
# After copying Eclipse needs to be restarted before the help appears.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_ECLIPSEHELP = NO
# A unique identifier for the Eclipse help plugin. When installing the plugin
# the directory name containing the HTML and XML files should also have this
# name. Each documentation set should have its own identifier.
# The default value is: org.doxygen.Project.
# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES.
ECLIPSE_DOC_ID = org.doxygen.Project
# If you want full control over the layout of the generated HTML pages it might
# be necessary to disable the index and replace it with your own. The
# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top
# of each HTML page. A value of NO enables the index and the value YES disables
# it. Since the tabs in the index contain the same information as the navigation
# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
DISABLE_INDEX = NO
# The GENERATE_TREEVIEW tag is used to specify whether a tree-like index
# structure should be generated to display hierarchical information. If the tag
# value is set to YES, a side panel will be generated containing a tree-like
# index structure (just like the one that is generated for HTML Help). For this
# to work a browser that supports JavaScript, DHTML, CSS and frames is required
# (i.e. any modern browser). Windows users are probably better off using the
# HTML help feature. Via custom style sheets (see HTML_EXTRA_STYLESHEET) one can
# further fine-tune the look of the index. As an example, the default style
# sheet generated by doxygen has an example that shows how to put an image at
# the root of the tree instead of the PROJECT_NAME. Since the tree basically has
# the same information as the tab index, you could consider setting
# DISABLE_INDEX to YES when enabling this option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
GENERATE_TREEVIEW = NO
# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that
# doxygen will group on one line in the generated HTML documentation.
#
# Note that a value of 0 will completely suppress the enum values from appearing
# in the overview section.
# Minimum value: 0, maximum value: 20, default value: 4.
# This tag requires that the tag GENERATE_HTML is set to YES.
ENUM_VALUES_PER_LINE = 4
# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used
# to set the initial width (in pixels) of the frame in which the tree is shown.
# Minimum value: 0, maximum value: 1500, default value: 250.
# This tag requires that the tag GENERATE_HTML is set to YES.
TREEVIEW_WIDTH = 250
# If the EXT_LINKS_IN_WINDOW option is set to YES, doxygen will open links to
# external symbols imported via tag files in a separate window.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
EXT_LINKS_IN_WINDOW = NO
# Use this tag to change the font size of LaTeX formulas included as images in
# the HTML documentation. When you change the font size after a successful
# doxygen run you need to manually remove any form_*.png images from the HTML
# output directory to force them to be regenerated.
# Minimum value: 8, maximum value: 50, default value: 10.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_FONTSIZE = 10
# Use the FORMULA_TRANPARENT tag to determine whether or not the images
# generated for formulas are transparent PNGs. Transparent PNGs are not
# supported properly for IE 6.0, but are supported on all modern browsers.
#
# Note that when changing this option you need to delete any form_*.png files in
# the HTML output directory before the changes have effect.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
FORMULA_TRANSPARENT = YES
# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see
# http://www.mathjax.org) which uses client side Javascript for the rendering
# instead of using pre-rendered bitmaps. Use this if you do not have LaTeX
# installed or if you want to formulas look prettier in the HTML output. When
# enabled you may also need to install MathJax separately and configure the path
# to it using the MATHJAX_RELPATH option.
# The default value is: NO.
# This tag requires that the tag GENERATE_HTML is set to YES.
USE_MATHJAX = NO
# When MathJax is enabled you can set the default output format to be used for
# the MathJax output. See the MathJax site (see:
# http://docs.mathjax.org/en/latest/output.html) for more details.
# Possible values are: HTML-CSS (which is slower, but has the best
# compatibility), NativeMML (i.e. MathML) and SVG.
# The default value is: HTML-CSS.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_FORMAT = HTML-CSS
# When MathJax is enabled you need to specify the location relative to the HTML
# output directory using the MATHJAX_RELPATH option. The destination directory
# should contain the MathJax.js script. For instance, if the mathjax directory
# is located at the same level as the HTML output directory, then
# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax
# Content Delivery Network so you can quickly see the result without installing
# MathJax. However, it is strongly recommended to install a local copy of
# MathJax from http://www.mathjax.org before deployment.
# The default value is: http://cdn.mathjax.org/mathjax/latest.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest
# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax
# extension names that should be enabled during MathJax rendering. For example
# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_EXTENSIONS =
# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces
# of code that will be used on startup of the MathJax code. See the MathJax site
# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an
# example see the documentation.
# This tag requires that the tag USE_MATHJAX is set to YES.
MATHJAX_CODEFILE =
# When the SEARCHENGINE tag is enabled doxygen will generate a search box for
# the HTML output. The underlying search engine uses javascript and DHTML and
# should work on any modern browser. Note that when using HTML help
# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET)
# there is already a search function so this one should typically be disabled.
# For large projects the javascript based search engine can be slow, then
# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to
# search using the keyboard; to jump to the search box use + S
# (what the is depends on the OS and browser, but it is typically
# , /, or both). Inside the search box use the to jump into the search results window, the results can be navigated
# using the . Press to select an item or to cancel
# the search. The filter options can be selected when the cursor is inside the
# search box by pressing +. Also here use the
# to select a filter and or to activate or cancel the filter
# option.
# The default value is: YES.
# This tag requires that the tag GENERATE_HTML is set to YES.
SEARCHENGINE = YES
# When the SERVER_BASED_SEARCH tag is enabled the search engine will be
# implemented using a web server instead of a web client using Javascript. There
# are two flavors of web server based searching depending on the EXTERNAL_SEARCH
# setting. When disabled, doxygen will generate a PHP script for searching and
# an index file used by the script. When EXTERNAL_SEARCH is enabled the indexing
# and searching needs to be provided by external tools. See the section
# "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
SERVER_BASED_SEARCH = NO
# When EXTERNAL_SEARCH tag is enabled doxygen will no longer generate the PHP
# script for searching. Instead the search results are written to an XML file
# which needs to be processed by an external indexer. Doxygen will invoke an
# external search engine pointed to by the SEARCHENGINE_URL option to obtain the
# search results.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/).
#
# See the section "External Indexing and Searching" for details.
# The default value is: NO.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH = NO
# The SEARCHENGINE_URL should point to a search engine hosted by a web server
# which will return the search results when EXTERNAL_SEARCH is enabled.
#
# Doxygen ships with an example indexer (doxyindexer) and search engine
# (doxysearch.cgi) which are based on the open source search engine library
# Xapian (see: http://xapian.org/). See the section "External Indexing and
# Searching" for details.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHENGINE_URL =
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the unindexed
# search data is written to a file for indexing by an external tool. With the
# SEARCHDATA_FILE tag the name of this file can be specified.
# The default file is: searchdata.xml.
# This tag requires that the tag SEARCHENGINE is set to YES.
SEARCHDATA_FILE = searchdata.xml
# When SERVER_BASED_SEARCH and EXTERNAL_SEARCH are both enabled the
# EXTERNAL_SEARCH_ID tag can be used as an identifier for the project. This is
# useful in combination with EXTRA_SEARCH_MAPPINGS to search through multiple
# projects and redirect the results back to the right project.
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTERNAL_SEARCH_ID =
# The EXTRA_SEARCH_MAPPINGS tag can be used to enable searching through doxygen
# projects other than the one defined by this configuration file, but that are
# all added to the same external search index. Each project needs to have a
# unique id set via EXTERNAL_SEARCH_ID. The search mapping then maps the id of
# to a relative location where the documentation can be found. The format is:
# EXTRA_SEARCH_MAPPINGS = tagname1=loc1 tagname2=loc2 ...
# This tag requires that the tag SEARCHENGINE is set to YES.
EXTRA_SEARCH_MAPPINGS =
#---------------------------------------------------------------------------
# Configuration options related to the LaTeX output
#---------------------------------------------------------------------------
# If the GENERATE_LATEX tag is set to YES, doxygen will generate LaTeX output.
# The default value is: YES.
GENERATE_LATEX = NO
# The LATEX_OUTPUT tag is used to specify where the LaTeX docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_OUTPUT = latex
# The LATEX_CMD_NAME tag can be used to specify the LaTeX command name to be
# invoked.
#
# Note that when enabling USE_PDFLATEX this option is only used for generating
# bitmaps for formulas in the HTML output, but not in the Makefile that is
# written to the output directory.
# The default file is: latex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_CMD_NAME = latex
# The MAKEINDEX_CMD_NAME tag can be used to specify the command name to generate
# index for LaTeX.
# The default file is: makeindex.
# This tag requires that the tag GENERATE_LATEX is set to YES.
MAKEINDEX_CMD_NAME = makeindex
# If the COMPACT_LATEX tag is set to YES, doxygen generates more compact LaTeX
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
COMPACT_LATEX = NO
# The PAPER_TYPE tag can be used to set the paper type that is used by the
# printer.
# Possible values are: a4 (210 x 297 mm), letter (8.5 x 11 inches), legal (8.5 x
# 14 inches) and executive (7.25 x 10.5 inches).
# The default value is: a4.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PAPER_TYPE = a4
# The EXTRA_PACKAGES tag can be used to specify one or more LaTeX package names
# that should be included in the LaTeX output. The package can be specified just
# by its name or with the correct syntax as to be used with the LaTeX
# \usepackage command. To get the times font for instance you can specify :
# EXTRA_PACKAGES=times or EXTRA_PACKAGES={times}
# To use the option intlimits with the amsmath package you can specify:
# EXTRA_PACKAGES=[intlimits]{amsmath}
# If left blank no extra packages will be included.
# This tag requires that the tag GENERATE_LATEX is set to YES.
EXTRA_PACKAGES =
# The LATEX_HEADER tag can be used to specify a personal LaTeX header for the
# generated LaTeX document. The header should contain everything until the first
# chapter. If it is left blank doxygen will generate a standard header. See
# section "Doxygen usage" for information on how to let doxygen write the
# default header to a separate file.
#
# Note: Only use a user-defined header if you know what you are doing! The
# following commands have a special meaning inside the header: $title,
# $datetime, $date, $doxygenversion, $projectname, $projectnumber,
# $projectbrief, $projectlogo. Doxygen will replace $title with the empty
# string, for the replacement values of the other commands the user is referred
# to HTML_HEADER.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HEADER =
# The LATEX_FOOTER tag can be used to specify a personal LaTeX footer for the
# generated LaTeX document. The footer should contain everything after the last
# chapter. If it is left blank doxygen will generate a standard footer. See
# LATEX_HEADER for more information on how to generate a default footer and what
# special commands can be used inside the footer.
#
# Note: Only use a user-defined footer if you know what you are doing!
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_FOOTER =
# The LATEX_EXTRA_STYLESHEET tag can be used to specify additional user-defined
# LaTeX style sheets that are included after the standard style sheets created
# by doxygen. Using this option one can overrule certain style aspects. Doxygen
# will copy the style sheet files to the output directory.
# Note: The order of the extra style sheet files is of importance (e.g. the last
# style sheet in the list overrules the setting of the previous ones in the
# list).
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_STYLESHEET =
# The LATEX_EXTRA_FILES tag can be used to specify one or more extra images or
# other source files which should be copied to the LATEX_OUTPUT output
# directory. Note that the files will be copied as-is; there are no commands or
# markers available.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_EXTRA_FILES =
# If the PDF_HYPERLINKS tag is set to YES, the LaTeX that is generated is
# prepared for conversion to PDF (using ps2pdf or pdflatex). The PDF file will
# contain links (just like the HTML output) instead of page references. This
# makes the output suitable for online browsing using a PDF viewer.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
PDF_HYPERLINKS = YES
# If the USE_PDFLATEX tag is set to YES, doxygen will use pdflatex to generate
# the PDF file directly from the LaTeX files. Set this option to YES, to get a
# higher quality PDF documentation.
# The default value is: YES.
# This tag requires that the tag GENERATE_LATEX is set to YES.
USE_PDFLATEX = YES
# If the LATEX_BATCHMODE tag is set to YES, doxygen will add the \batchmode
# command to the generated LaTeX files. This will instruct LaTeX to keep running
# if errors occur, instead of asking the user for help. This option is also used
# when generating formulas in HTML.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BATCHMODE = NO
# If the LATEX_HIDE_INDICES tag is set to YES then doxygen will not include the
# index chapters (such as File Index, Compound Index, etc.) in the output.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_HIDE_INDICES = NO
# If the LATEX_SOURCE_CODE tag is set to YES then doxygen will include source
# code with syntax highlighting in the LaTeX output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_SOURCE_CODE = NO
# The LATEX_BIB_STYLE tag can be used to specify the style to use for the
# bibliography, e.g. plainnat, or ieeetr. See
# http://en.wikipedia.org/wiki/BibTeX and \cite for more info.
# The default value is: plain.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_BIB_STYLE = plain
# If the LATEX_TIMESTAMP tag is set to YES then the footer of each generated
# page will contain the date and time when the page was generated. Setting this
# to NO can help when comparing the output of multiple runs.
# The default value is: NO.
# This tag requires that the tag GENERATE_LATEX is set to YES.
LATEX_TIMESTAMP = NO
#---------------------------------------------------------------------------
# Configuration options related to the RTF output
#---------------------------------------------------------------------------
# If the GENERATE_RTF tag is set to YES, doxygen will generate RTF output. The
# RTF output is optimized for Word 97 and may not look too pretty with other RTF
# readers/editors.
# The default value is: NO.
GENERATE_RTF = NO
# The RTF_OUTPUT tag is used to specify where the RTF docs will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: rtf.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_OUTPUT = rtf
# If the COMPACT_RTF tag is set to YES, doxygen generates more compact RTF
# documents. This may be useful for small projects and may help to save some
# trees in general.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
COMPACT_RTF = NO
# If the RTF_HYPERLINKS tag is set to YES, the RTF that is generated will
# contain hyperlink fields. The RTF file will contain links (just like the HTML
# output) instead of page references. This makes the output suitable for online
# browsing using Word or some other Word compatible readers that support those
# fields.
#
# Note: WordPad (write) and others do not support links.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_HYPERLINKS = NO
# Load stylesheet definitions from file. Syntax is similar to doxygen's config
# file, i.e. a series of assignments. You only have to provide replacements,
# missing definitions are set to their default value.
#
# See also section "Doxygen usage" for information on how to generate the
# default style sheet that doxygen normally uses.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_STYLESHEET_FILE =
# Set optional variables used in the generation of an RTF document. Syntax is
# similar to doxygen's config file. A template extensions file can be generated
# using doxygen -e rtf extensionFile.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_EXTENSIONS_FILE =
# If the RTF_SOURCE_CODE tag is set to YES then doxygen will include source code
# with syntax highlighting in the RTF output.
#
# Note that which sources are shown also depends on other settings such as
# SOURCE_BROWSER.
# The default value is: NO.
# This tag requires that the tag GENERATE_RTF is set to YES.
RTF_SOURCE_CODE = NO
#---------------------------------------------------------------------------
# Configuration options related to the man page output
#---------------------------------------------------------------------------
# If the GENERATE_MAN tag is set to YES, doxygen will generate man pages for
# classes and files.
# The default value is: NO.
GENERATE_MAN = YES
# The MAN_OUTPUT tag is used to specify where the man pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it. A directory man3 will be created inside the directory specified by
# MAN_OUTPUT.
# The default directory is: man.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_OUTPUT = man
# The MAN_EXTENSION tag determines the extension that is added to the generated
# man pages. In case the manual section does not start with a number, the number
# 3 is prepended. The dot (.) at the beginning of the MAN_EXTENSION tag is
# optional.
# The default value is: .3.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_EXTENSION = .3
# The MAN_SUBDIR tag determines the name of the directory created within
# MAN_OUTPUT in which the man pages are placed. If defaults to man followed by
# MAN_EXTENSION with the initial . removed.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_SUBDIR =
# If the MAN_LINKS tag is set to YES and doxygen generates man output, then it
# will generate one additional man file for each entity documented in the real
# man page(s). These additional files only source the real man page, but without
# them the man command would be unable to find the correct page.
# The default value is: NO.
# This tag requires that the tag GENERATE_MAN is set to YES.
MAN_LINKS = YES
#---------------------------------------------------------------------------
# Configuration options related to the XML output
#---------------------------------------------------------------------------
# If the GENERATE_XML tag is set to YES, doxygen will generate an XML file that
# captures the structure of the code including all documentation.
# The default value is: NO.
GENERATE_XML = NO
# The XML_OUTPUT tag is used to specify where the XML pages will be put. If a
# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of
# it.
# The default directory is: xml.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_OUTPUT = xml
# If the XML_PROGRAMLISTING tag is set to YES, doxygen will dump the program
# listings (including syntax highlighting and cross-referencing information) to
# the XML output. Note that enabling this will significantly increase the size
# of the XML output.
# The default value is: YES.
# This tag requires that the tag GENERATE_XML is set to YES.
XML_PROGRAMLISTING = YES
#---------------------------------------------------------------------------
# Configuration options related to the DOCBOOK output
#---------------------------------------------------------------------------
# If the GENERATE_DOCBOOK tag is set to YES, doxygen will generate Docbook files
# that can be used to generate PDF.
# The default value is: NO.
GENERATE_DOCBOOK = NO
# The DOCBOOK_OUTPUT tag is used to specify where the Docbook pages will be put.
# If a relative path is entered the value of OUTPUT_DIRECTORY will be put in
# front of it.
# The default directory is: docbook.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_OUTPUT = docbook
# If the DOCBOOK_PROGRAMLISTING tag is set to YES, doxygen will include the
# program listings (including syntax highlighting and cross-referencing
# information) to the DOCBOOK output. Note that enabling this will significantly
# increase the size of the DOCBOOK output.
# The default value is: NO.
# This tag requires that the tag GENERATE_DOCBOOK is set to YES.
DOCBOOK_PROGRAMLISTING = NO
#---------------------------------------------------------------------------
# Configuration options for the AutoGen Definitions output
#---------------------------------------------------------------------------
# If the GENERATE_AUTOGEN_DEF tag is set to YES, doxygen will generate an
# AutoGen Definitions (see http://autogen.sf.net) file that captures the
# structure of the code including all documentation. Note that this feature is
# still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_AUTOGEN_DEF = NO
#---------------------------------------------------------------------------
# Configuration options related to the Perl module output
#---------------------------------------------------------------------------
# If the GENERATE_PERLMOD tag is set to YES, doxygen will generate a Perl module
# file that captures the structure of the code including all documentation.
#
# Note that this feature is still experimental and incomplete at the moment.
# The default value is: NO.
GENERATE_PERLMOD = NO
# If the PERLMOD_LATEX tag is set to YES, doxygen will generate the necessary
# Makefile rules, Perl scripts and LaTeX code to be able to generate PDF and DVI
# output from the Perl module output.
# The default value is: NO.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_LATEX = NO
# If the PERLMOD_PRETTY tag is set to YES, the Perl module output will be nicely
# formatted so it can be parsed by a human reader. This is useful if you want to
# understand what is going on. On the other hand, if this tag is set to NO, the
# size of the Perl module output will be much smaller and Perl will parse it
# just the same.
# The default value is: YES.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_PRETTY = YES
# The names of the make variables in the generated doxyrules.make file are
# prefixed with the string contained in PERLMOD_MAKEVAR_PREFIX. This is useful
# so different doxyrules.make files included by the same Makefile don't
# overwrite each other's variables.
# This tag requires that the tag GENERATE_PERLMOD is set to YES.
PERLMOD_MAKEVAR_PREFIX =
#---------------------------------------------------------------------------
# Configuration options related to the preprocessor
#---------------------------------------------------------------------------
# If the ENABLE_PREPROCESSING tag is set to YES, doxygen will evaluate all
# C-preprocessor directives found in the sources and include files.
# The default value is: YES.
ENABLE_PREPROCESSING = YES
# If the MACRO_EXPANSION tag is set to YES, doxygen will expand all macro names
# in the source code. If set to NO, only conditional compilation will be
# performed. Macro expansion can be done in a controlled way by setting
# EXPAND_ONLY_PREDEF to YES.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
MACRO_EXPANSION = YES
# If the EXPAND_ONLY_PREDEF and MACRO_EXPANSION tags are both set to YES then
# the macro expansion is limited to the macros specified with the PREDEFINED and
# EXPAND_AS_DEFINED tags.
# The default value is: NO.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_ONLY_PREDEF = YES
# If the SEARCH_INCLUDES tag is set to YES, the include files in the
# INCLUDE_PATH will be searched if a #include is found.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SEARCH_INCLUDES = YES
# The INCLUDE_PATH tag can be used to specify one or more directories that
# contain include files that are not input files but should be processed by the
# preprocessor.
# This tag requires that the tag SEARCH_INCLUDES is set to YES.
INCLUDE_PATH =
# You can use the INCLUDE_FILE_PATTERNS tag to specify one or more wildcard
# patterns (like *.h and *.hpp) to filter out the header-files in the
# directories. If left blank, the patterns specified with FILE_PATTERNS will be
# used.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
INCLUDE_FILE_PATTERNS =
# The PREDEFINED tag can be used to specify one or more macro names that are
# defined before the preprocessor is started (similar to the -D option of e.g.
# gcc). The argument of the tag is a list of macros of the form: name or
# name=definition (no spaces). If the definition and the "=" are omitted, "=1"
# is assumed. To prevent a macro definition from being undefined via #undef or
# recursively expanded use the := operator instead of the = operator.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
PREDEFINED = _ARCH_PPC64 _DOXYGEN_ LIBOCXL_WARN_UNUSED=
# If the MACRO_EXPANSION and EXPAND_ONLY_PREDEF tags are set to YES then this
# tag can be used to specify a list of macro names that should be expanded. The
# macro definition that is found in the sources will be used. Use the PREDEFINED
# tag if you want to use a different macro definition that overrules the
# definition found in the source code.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
EXPAND_AS_DEFINED = LIBOCXL_WARN_UNUSED
# If the SKIP_FUNCTION_MACROS tag is set to YES then doxygen's preprocessor will
# remove all references to function-like macros that are alone on a line, have
# an all uppercase name, and do not end with a semicolon. Such function macros
# are typically used for boiler-plate code, and will confuse the parser if not
# removed.
# The default value is: YES.
# This tag requires that the tag ENABLE_PREPROCESSING is set to YES.
SKIP_FUNCTION_MACROS = YES
#---------------------------------------------------------------------------
# Configuration options related to external references
#---------------------------------------------------------------------------
# The TAGFILES tag can be used to specify one or more tag files. For each tag
# file the location of the external documentation should be added. The format of
# a tag file without this location is as follows:
# TAGFILES = file1 file2 ...
# Adding location for the tag files is done as follows:
# TAGFILES = file1=loc1 "file2 = loc2" ...
# where loc1 and loc2 can be relative or absolute paths or URLs. See the
# section "Linking to external documentation" for more information about the use
# of tag files.
# Note: Each tag file must have a unique name (where the name does NOT include
# the path). If a tag file is not located in the directory in which doxygen is
# run, you must also specify the path to the tagfile here.
TAGFILES =
# When a file name is specified after GENERATE_TAGFILE, doxygen will create a
# tag file that is based on the input files it reads. See section "Linking to
# external documentation" for more information about the usage of tag files.
GENERATE_TAGFILE =
# If the ALLEXTERNALS tag is set to YES, all external class will be listed in
# the class index. If set to NO, only the inherited external classes will be
# listed.
# The default value is: NO.
ALLEXTERNALS = NO
# If the EXTERNAL_GROUPS tag is set to YES, all external groups will be listed
# in the modules index. If set to NO, only the current project's groups will be
# listed.
# The default value is: YES.
EXTERNAL_GROUPS = YES
# If the EXTERNAL_PAGES tag is set to YES, all external pages will be listed in
# the related pages index. If set to NO, only the current project's pages will
# be listed.
# The default value is: YES.
EXTERNAL_PAGES = YES
# The PERL_PATH should be the absolute path and name of the perl script
# interpreter (i.e. the result of 'which perl').
# The default file (with absolute path) is: /usr/bin/perl.
PERL_PATH = /usr/bin/perl
#---------------------------------------------------------------------------
# Configuration options related to the dot tool
#---------------------------------------------------------------------------
# If the CLASS_DIAGRAMS tag is set to YES, doxygen will generate a class diagram
# (in HTML and LaTeX) for classes with base or super classes. Setting the tag to
# NO turns the diagrams off. Note that this option also works with HAVE_DOT
# disabled, but it is recommended to install and use dot, since it yields more
# powerful graphs.
# The default value is: YES.
CLASS_DIAGRAMS = YES
# You can define message sequence charts within doxygen comments using the \msc
# command. Doxygen will then run the mscgen tool (see:
# http://www.mcternan.me.uk/mscgen/)) to produce the chart and insert it in the
# documentation. The MSCGEN_PATH tag allows you to specify the directory where
# the mscgen tool resides. If left empty the tool is assumed to be found in the
# default search path.
MSCGEN_PATH =
# You can include diagrams made with dia in doxygen documentation. Doxygen will
# then run dia to produce the diagram and insert it in the documentation. The
# DIA_PATH tag allows you to specify the directory where the dia binary resides.
# If left empty dia is assumed to be found in the default search path.
DIA_PATH =
# If set to YES the inheritance and collaboration graphs will hide inheritance
# and usage relations if the target is undocumented or is not a class.
# The default value is: YES.
HIDE_UNDOC_RELATIONS = YES
# If you set the HAVE_DOT tag to YES then doxygen will assume the dot tool is
# available from the path. This tool is part of Graphviz (see:
# http://www.graphviz.org/), a graph visualization toolkit from AT&T and Lucent
# Bell Labs. The other options in this section have no effect if this option is
# set to NO
# The default value is: NO.
HAVE_DOT = NO
# The DOT_NUM_THREADS specifies the number of dot invocations doxygen is allowed
# to run in parallel. When set to 0 doxygen will base this on the number of
# processors available in the system. You can set it explicitly to a value
# larger than 0 to get control over the balance between CPU load and processing
# speed.
# Minimum value: 0, maximum value: 32, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_NUM_THREADS = 0
# When you want a differently looking font in the dot files that doxygen
# generates you can specify the font name using DOT_FONTNAME. You need to make
# sure dot is able to find the font, which can be done by putting it in a
# standard location or by setting the DOTFONTPATH environment variable or by
# setting DOT_FONTPATH to the directory containing the font.
# The default value is: Helvetica.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTNAME = Helvetica
# The DOT_FONTSIZE tag can be used to set the size (in points) of the font of
# dot graphs.
# Minimum value: 4, maximum value: 24, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTSIZE = 10
# By default doxygen will tell dot to use the default font as specified with
# DOT_FONTNAME. If you specify a different font using DOT_FONTNAME you can set
# the path where dot can find it using this tag.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_FONTPATH =
# If the CLASS_GRAPH tag is set to YES then doxygen will generate a graph for
# each documented class showing the direct and indirect inheritance relations.
# Setting this tag to YES will force the CLASS_DIAGRAMS tag to NO.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
CLASS_GRAPH = YES
# If the COLLABORATION_GRAPH tag is set to YES then doxygen will generate a
# graph for each documented class showing the direct and indirect implementation
# dependencies (inheritance, containment, and class references variables) of the
# class with other documented classes.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
COLLABORATION_GRAPH = YES
# If the GROUP_GRAPHS tag is set to YES then doxygen will generate a graph for
# groups, showing the direct groups dependencies.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GROUP_GRAPHS = YES
# If the UML_LOOK tag is set to YES, doxygen will generate inheritance and
# collaboration diagrams in a style similar to the OMG's Unified Modeling
# Language.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LOOK = NO
# If the UML_LOOK tag is enabled, the fields and methods are shown inside the
# class node. If there are many fields or methods and many nodes the graph may
# become too big to be useful. The UML_LIMIT_NUM_FIELDS threshold limits the
# number of items for each type to make the size more manageable. Set this to 0
# for no limit. Note that the threshold may be exceeded by 50% before the limit
# is enforced. So when you set the threshold to 10, up to 15 fields may appear,
# but if the number exceeds 15, the total amount of fields shown is limited to
# 10.
# Minimum value: 0, maximum value: 100, default value: 10.
# This tag requires that the tag HAVE_DOT is set to YES.
UML_LIMIT_NUM_FIELDS = 10
# If the TEMPLATE_RELATIONS tag is set to YES then the inheritance and
# collaboration graphs will show the relations between templates and their
# instances.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
TEMPLATE_RELATIONS = NO
# If the INCLUDE_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are set to
# YES then doxygen will generate a graph for each documented file showing the
# direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDE_GRAPH = YES
# If the INCLUDED_BY_GRAPH, ENABLE_PREPROCESSING and SEARCH_INCLUDES tags are
# set to YES then doxygen will generate a graph for each documented file showing
# the direct and indirect include dependencies of the file with other documented
# files.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
INCLUDED_BY_GRAPH = YES
# If the CALL_GRAPH tag is set to YES then doxygen will generate a call
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable call graphs for selected
# functions only using the \callgraph command. Disabling a call graph can be
# accomplished by means of the command \hidecallgraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALL_GRAPH = NO
# If the CALLER_GRAPH tag is set to YES then doxygen will generate a caller
# dependency graph for every global function or class method.
#
# Note that enabling this option will significantly increase the time of a run.
# So in most cases it will be better to enable caller graphs for selected
# functions only using the \callergraph command. Disabling a caller graph can be
# accomplished by means of the command \hidecallergraph.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
CALLER_GRAPH = NO
# If the GRAPHICAL_HIERARCHY tag is set to YES then doxygen will graphical
# hierarchy of all classes instead of a textual one.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GRAPHICAL_HIERARCHY = YES
# If the DIRECTORY_GRAPH tag is set to YES then doxygen will show the
# dependencies a directory has on other directories in a graphical way. The
# dependency relations are determined by the #include relations between the
# files in the directories.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DIRECTORY_GRAPH = YES
# The DOT_IMAGE_FORMAT tag can be used to set the image format of the images
# generated by dot. For an explanation of the image formats see the section
# output formats in the documentation of the dot tool (Graphviz (see:
# http://www.graphviz.org/)).
# Note: If you choose svg you need to set HTML_FILE_EXTENSION to xhtml in order
# to make the SVG files visible in IE 9+ (other browsers do not have this
# requirement).
# Possible values are: png, jpg, gif, svg, png:gd, png:gd:gd, png:cairo,
# png:cairo:gd, png:cairo:cairo, png:cairo:gdiplus, png:gdiplus and
# png:gdiplus:gdiplus.
# The default value is: png.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_IMAGE_FORMAT = png
# If DOT_IMAGE_FORMAT is set to svg, then this option can be set to YES to
# enable generation of interactive SVG images that allow zooming and panning.
#
# Note that this requires a modern browser other than Internet Explorer. Tested
# and working are Firefox, Chrome, Safari, and Opera.
# Note: For IE 9+ you need to set HTML_FILE_EXTENSION to xhtml in order to make
# the SVG files visible. Older versions of IE do not have SVG support.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
INTERACTIVE_SVG = NO
# The DOT_PATH tag can be used to specify the path where the dot tool can be
# found. If left blank, it is assumed the dot tool can be found in the path.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_PATH =
# The DOTFILE_DIRS tag can be used to specify one or more directories that
# contain dot files that are included in the documentation (see the \dotfile
# command).
# This tag requires that the tag HAVE_DOT is set to YES.
DOTFILE_DIRS =
# The MSCFILE_DIRS tag can be used to specify one or more directories that
# contain msc files that are included in the documentation (see the \mscfile
# command).
MSCFILE_DIRS =
# The DIAFILE_DIRS tag can be used to specify one or more directories that
# contain dia files that are included in the documentation (see the \diafile
# command).
DIAFILE_DIRS =
# When using plantuml, the PLANTUML_JAR_PATH tag should be used to specify the
# path where java can find the plantuml.jar file. If left blank, it is assumed
# PlantUML is not used or called during a preprocessing step. Doxygen will
# generate a warning when it encounters a \startuml command in this case and
# will not generate output for the diagram.
PLANTUML_JAR_PATH =
# When using plantuml, the PLANTUML_CFG_FILE tag can be used to specify a
# configuration file for plantuml.
PLANTUML_CFG_FILE =
# When using plantuml, the specified paths are searched for files specified by
# the !include statement in a plantuml block.
PLANTUML_INCLUDE_PATH =
# The DOT_GRAPH_MAX_NODES tag can be used to set the maximum number of nodes
# that will be shown in the graph. If the number of nodes in a graph becomes
# larger than this value, doxygen will truncate the graph, which is visualized
# by representing a node as a red box. Note that doxygen if the number of direct
# children of the root node in a graph is already larger than
# DOT_GRAPH_MAX_NODES then the graph will not be shown at all. Also note that
# the size of a graph can be further restricted by MAX_DOT_GRAPH_DEPTH.
# Minimum value: 0, maximum value: 10000, default value: 50.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_GRAPH_MAX_NODES = 50
# The MAX_DOT_GRAPH_DEPTH tag can be used to set the maximum depth of the graphs
# generated by dot. A depth value of 3 means that only nodes reachable from the
# root by following a path via at most 3 edges will be shown. Nodes that lay
# further from the root node will be omitted. Note that setting this option to 1
# or 2 may greatly reduce the computation time needed for large code bases. Also
# note that the size of a graph can be further restricted by
# DOT_GRAPH_MAX_NODES. Using a depth of 0 means no depth restriction.
# Minimum value: 0, maximum value: 1000, default value: 0.
# This tag requires that the tag HAVE_DOT is set to YES.
MAX_DOT_GRAPH_DEPTH = 0
# Set the DOT_TRANSPARENT tag to YES to generate images with a transparent
# background. This is disabled by default, because dot on Windows does not seem
# to support this out of the box.
#
# Warning: Depending on the platform used, enabling this option may lead to
# badly anti-aliased labels on the edges of a graph (i.e. they become hard to
# read).
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_TRANSPARENT = NO
# Set the DOT_MULTI_TARGETS tag to YES to allow dot to generate multiple output
# files in one run (i.e. multiple -o and -T options on the command line). This
# makes dot run faster, but since only newer versions of dot (>1.8.10) support
# this, this feature is disabled by default.
# The default value is: NO.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_MULTI_TARGETS = NO
# If the GENERATE_LEGEND tag is set to YES doxygen will generate a legend page
# explaining the meaning of the various boxes and arrows in the dot generated
# graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
GENERATE_LEGEND = YES
# If the DOT_CLEANUP tag is set to YES, doxygen will remove the intermediate dot
# files that are used to generate the various graphs.
# The default value is: YES.
# This tag requires that the tag HAVE_DOT is set to YES.
DOT_CLEANUP = YES
libocxl-1.1.0/Makefile 0000664 0000000 0000000 00000011160 13332436400 0014602 0 ustar 00root root 0000000 0000000 srcdir = $(PWD)
include Makefile.vars
OBJS = obj/afu.o obj/internal.o obj/irq.o obj/mmio.o obj/setup.o
TEST_OBJS = testobj/afu.o testobj/internal.o testobj/irq.o testobj/mmio.o testobj/setup.o
CFLAGS += -I src/include -I kernel/include -fPIC -D_FILE_OFFSET_BITS=64
VERS_LIB = $(VERSION_MAJOR).$(VERSION_MINOR)
LIBNAME = libocxl.so.$(VERS_LIB)
LIBSONAME = libocxl.so.$(VERSION_MAJOR)
SONAMEOPT = -Wl,-soname,$(LIBSONAME)
DOCDIR = docs
all: check_ocxl_header obj/$(LIBSONAME) obj/libocxl.so obj/libocxl.a sampleobj/memcpy
HAS_WGET = $(shell /bin/which wget > /dev/null 2>&1 && echo y || echo n)
HAS_CURL = $(shell /bin/which curl > /dev/null 2>&1 && echo y || echo n)
# Update this to test a single feature from the most recent header we require:
CHECK_OCXL_HEADER_IS_UP_TO_DATE = $(shell /bin/echo -e \\\#include $(1)\\\nvoid test\(struct ocxl_ioctl_features test\)\; | \
$(CC) $(CFLAGS) -Werror -x c -S -o /dev/null - > /dev/null 2>&1 && echo y || echo n)
check_ocxl_header:
ifeq ($(call CHECK_OCXL_HEADER_IS_UP_TO_DATE,''),n)
mkdir -p kernel/include/misc
ifeq (${HAS_WGET},y)
$(call Q,WGET kernel/include/misc/ocxl.h, wget -O kernel/include/misc/ocxl.h -q http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/ocxl.h)
else ifeq (${HAS_CURL},y)
$(call Q,CURL kernel/include/misc/ocxl.h, curl -o kernel/include/misc/ocxl.h -s http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/ocxl.h)
else
$(error 'ocxl.h is non-existant or out of date, Download from http://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/plain/include/uapi/misc/ocxl.h and place in ${PWD}/kernel/include/misc/ocxl.h')
endif
endif
src/libocxl_info.h: version.pl
VERSION_MAJOR=${VERSION_MAJOR} VERSION_MINOR=${VERSION_MINOR} \
VERSION_PATCH=${VERSION_PATCH} CC="${CC}" CFLAGS="${CFLAGS}" \
./version.pl > src/libocxl_info.h
obj:
mkdir obj
obj/libocxl.so: obj/$(LIBNAME)
ln -sf $(LIBNAME) obj/libocxl.so
obj/$(LIBSONAME): obj/$(LIBNAME)
ln -sf $(LIBNAME) obj/$(LIBSONAME)
obj/$(LIBNAME): $(OBJS) symver.map
$(call Q,CC, $(CC) $(CFLAGS) $(LDFLAGS) -shared $(OBJS) -o obj/$(LIBNAME), obj/$(LIBNAME)) -Wl,--version-script symver.map $(SONAMEOPT)
obj/libocxl.a: $(OBJS)
$(call Q,AR, $(AR) rcs obj/libocxl.a $(OBJS), obj/libocxl.a)
sampleobj/memcpy: sampleobj/memcpy.o-memcpy
$(call Q,CC, $(CC) $(CFLAGS) $(LDFLAGS) -o sampleobj/memcpy sampleobj/memcpy.o-memcpy obj/libocxl.a, sampleobj/memcpy)
testobj:
mkdir testobj
sampleobj:
mkdir sampleobj
testobj/libocxl.a: $(TEST_OBJS)
$(call Q,AR, $(AR) rcs testobj/libocxl-temp.a $(TEST_OBJS), testobj/libocxl-temp.a)
$(call Q,STATIC_SYMS, $(NM) testobj/libocxl-temp.a | grep ' t ' | grep -v __ | cut -d ' ' -f 3 > testobj/static-syms)
$(call Q,STATIC_PROTOTYPES, perl -n static-prototypes.pl src/*.c >testobj/static.h)
$(call Q,OBJCOPY, $(OBJCOPY) --globalize-symbols=testobj/static-syms testobj/libocxl-temp.a testobj/libocxl.a, obj/libocxl.a)
testobj/unittests: testobj/unittests.o-test testobj/virtocxl.o-test
$(call Q,CC, $(CC) $(CFLAGS) $(LDFLAGS) -o testobj/unittests testobj/unittests.o-test testobj/virtocxl.o-test testobj/libocxl.a -lfuse -lpthread, testobj/unittests)
test: check_ocxl_header testobj/unittests
sudo testobj/unittests
valgrind: testobj/unittests
sudo valgrind testobj/unittests
include Makefile.rules
cppcheck:
cppcheck --enable=all -j 4 -q src/*.c src/include/libocxl.h
cppcheck-xml:
cppcheck --enable=all -j 4 -q src/*.c src/include/libocxl.h --xml-version=2 2>cppcheck.xml
precommit: clean all docs cppcheck
astyle --style=linux --indent=tab=8 --max-code-length=120 src/*.c src/*.h src/include/*.h samples/*/*.c
$(call Q, SYMVER-CHECK, nm obj/$(LIBNAME) | grep ' t ocxl' && (echo "Symbols are missing from symver.map" && exit 1) || true)
docs:
rm -rf $(DOCDIR)
$(call Q,DOCS-MAN, doxygen Doxyfile-man,)
cd docs/man/man3 && \
ls | grep -vi ocxl | xargs rm
$(call Q,DOCS-HTML, doxygen Doxyfile-html,)
clean:
rm -rf obj testobj sampleobj docs src/libocxl_info.h
install: all docs
mkdir -p $(DESTDIR)$(libdir)
mkdir -p $(DESTDIR)$(includedir)
mkdir -p $(DESTDIR)$(mandir)/man3
mkdir -p $(DESTDIR)$(docdir)/libocxl/search
$(INSTALL) -m 0755 obj/$(LIBNAME) $(DESTDIR)$(libdir)/
ln -s $(LIBNAME) $(DESTDIR)$(libdir)/$(LIBSONAME)
ln -s $(LIBNAME) $(DESTDIR)$(libdir)/libocxl.so
$(INSTALL) -m 0644 src/include/libocxl.h $(DESTDIR)$(includedir)/
$(INSTALL) -m 0644 -D docs/man/man3/* $(DESTDIR)$(mandir)/man3
$(INSTALL) -m 0644 -D docs/html/*.* $(DESTDIR)$(docdir)/libocxl
$(INSTALL) -m 0644 -D docs/html/search/* $(DESTDIR)$(docdir)/libocxl/search
.PHONY: clean all install docs precommit cppcheck cppcheck-xml check_ocxl_header
libocxl-1.1.0/Makefile.rules 0000664 0000000 0000000 00000001656 13332436400 0015744 0 ustar 00root root 0000000 0000000 # Basic makefile rules
PREFIX ?= /usr/local
ifdef V
VERBOSE:= $(V)
else
VERBOSE:= 0
endif
ifeq ($(VERBOSE),1)
define Q
$(2)
endef
else
define Q
@/bin/echo -e " [$1]\t$(3)"
@$(2)
endef
endif
obj/%.o : src/%.c src/include/libocxl.h src/libocxl_internal.h src/libocxl_info.h | obj
$(call Q,CC, $(CC) $(CPPFLAGS) $(CFLAGS) -c -o $@ $<, $@)
testobj/%.o : src/%.c src/include/libocxl.h src/libocxl_internal.h src/libocxl_info.h | testobj
$(call Q,CC, $(CC) $(CPPFLAGS) $(TESTCFLAGS) -c -o $@ $<, $@)
testobj/%.o-test : unittests/%.c testobj/libocxl.a | testobj
$(call Q,CC, $(CC) $(CPPFLAGS) $(TESTCFLAGS) -c -o $@ $<, $@)
sampleobj/%.o-memcpy : samples/memcpy/%.c obj/libocxl.a | sampleobj
$(call Q,CC, $(CC) $(CPPFLAGS) $(SAMPLECFLAGS) -c -o $@ $<, $@)
datadir ?= $(PREFIX)/share
includedir ?= $(PREFIX)/include
mandir ?= $(datadir)/man
docdir ?= $(datadir)/doc
libdir ?= $(PREFIX)/lib64
INSTALL ?= install -p
libocxl-1.1.0/Makefile.vars 0000664 0000000 0000000 00000001221 13332436400 0015551 0 ustar 00root root 0000000 0000000 # Disable built-in rules
MAKEFLAGS += -rR
# change VERSION_MAJOR only if library breaks backward compatibility.
# refer to file symver.map
VERSION_MAJOR = 1
# Change VERSION_MINOR on new features
VERSION_MINOR = 1
# Change VERSION_PATCH on each tag
VERSION_PATCH = 0
AR = $(CROSS_COMPILE)ar
AS = $(CROSS_COMPILE)as
LD = $(CROSS_COMPILE)ld
CC = $(CROSS_COMPILE)gcc
NM = $(CROSS_COMPILE)nm
OBJCOPY = $(CROSS_COMPILE)objcopy
CFLAGS ?= -g -Wall -Wextra -O2 -m64 -std=c11 -DLIBOCXL_SUPPRESS_INACCESSIBLE_WARNINGS
TESTCFLAGS += $(CFLAGS) -O0 -DTEST_ENVIRONMENT=1 -I src -I testobj -pthread
SAMPLECFLAGS += $(CFLAGS) -std=gnu11 -I src -I testobj -pthread libocxl-1.1.0/README.md 0000664 0000000 0000000 00000011201 13332436400 0014415 0 ustar 00root root 0000000 0000000 # Introduction
LibOCXL provides an access library which allows the user to implement a userspace
driver for an [OpenCAPI](http://opencapi.org/about/) accelerator.
# Features
## Initialization
AFUs may be opened using the device path or AFU name. If an multiple AFU instances
with the same name are available, the first AFU found with available contexts will
be used.
## Operation
LibOCXL provides functions to attach to an AFU and transfer data to & from the MMIO areas
on the AFU. AFU IRQs can be queried either by IRQ handles, or by associating a callback
to the IRQ.
## MMIO
Functions are provide to allow 32 & 64 bit access to the global and per-PASID MMIO
areas on the the AFU. Endian conversion is handled automatically.
# Building
## Prerequisites
1. A GCC toolchain with libc (if cross compiling), crosstool-ng can build a suitable toolchain
if your cross compiler does not include libc.
2. [Doxygen](http://www.stack.nl/~dimitri/doxygen/) 1.8.14 or later. Earlier versions will work, but don't generate enums in the man
pages correctly.
3. [Astyle](http://astyle.sourceforge.net/), if you plan on submitting patches.
4. [CPPCheck](http://cppcheck.sourceforge.net/), if you plan on submitting patches.
5. [libFUSE](https://github.com/libfuse/libfuse), to run tests
## Included Dependencies
- OCXL headers from the [Linux kernel](https://www.kernel.org/)
## Build Instructions (Local build)
- `make`
- `PREFIX=/usr/local make install`
## Build Instructions (Cross compilation)
- `export CROSS_COMPILE=/path/to/compiler/bin/powerpc64le-unknown-linux-gnu-`
- `make`
# Usage
A typical use of libocxl will follow this pattern:
1. **Setup:** optionally turn on error reporting for the open calls: ocxl\_enable\_messages().
2. **Open the device:** ocxl\_afu\_open() if an AFU name is used, or ocxl\_afu\_open\_from\_dev() if
a device path is used. Optionally turn on error reporting for the AFU: ocxl\_afu\_enable\_messages().
3. **Allocate IRQs:** ocxl\_irq\_alloc(). This returns a sequential per-AFU IRQ number.
An opaque pointer is associated with the
handle in which the caller can store additional information. This is not used by OpenCAPI,
but is passed as part of the event information to provide additional context to the IRQ handler.
4. **Configure global MMIO:** Some AFUs may have a global MMIO area, which will contain configuration
information that will affect all PASIDs on the AFU. Use ocxl\_mmio\_map() to make the area available,
then use ocxl\_mmio\_write32() and ocxl\_mmio\_write64() to write the information.
5. **Configure the per-PASID MMIO:** Some AFUs support multiple contexts, and each context will
get it's own MMIO area for configuration and communication. Typical information that may
be communicated across the MMIO interface include IRQ handles (obtained with
ocxl\_irq\_get\_handle()), and pointers to AFU-specific
data structures. Use ocxl\_mmio\_map to make the area available, then use
ocxl\_mmio\_write32() and ocxl\_mmio\_write64() to write the information.
6. **Attach the AFU context to the process:** Use ocxl\_afu\_attach() to make the process's address space available
to the AFU context, allowing it to read & write to the process's memory.
7. **Signal the AFU to do some work:** This is typically done via a write into the per-PASID MMIO area.
8. **Handle AFU IRQs:** Pending IRQs can be queried using ocxl\_afu\_event\_check(). An IRQ event
contains the IRQ number, the info pointer assigned when activated, the 64 bit IRQ handle, and
the number of times the IRQ has been triggered since last checked.
9. **Read results:** Work completion may be signalled by the AFU via an IRQ, or by writing to
the MMIO area. Typically, bulk data should be written to a pointer passed to the AFU, however,
small quantities of data may be read from an MMIO area using ocxl\_mmio\_read32() and
ocxl\_mmio\_read64().
10. **Termination:** ocxl\_afu\_close() will free all resources associated with an AFU handle.
# Development
The following environment variables may be set (to 1 or "YES") to assist with development:
**LIBOCXL_INFO** Print information about the LibOCXL build to stderr. This should be included in any bug reports.
**LIBOCXL_TRACE_ALL** Force AFU interaction trace messages to be emitted for all AFUs unless explicitly disabled.
**LIBOCXL_VERBOSE_ERRORS_ALL** Force verbose errors to be emitted for any failed LibOCXL calls, unless explicitly disabled.
Patches may be submitted via Github pull requests. Please prepare your patches
by running `make precommit` before committing your work, and addressing any warnings & errors reported.
Patches must compile cleanly with the latest stable version of GCC to be accepted.
libocxl-1.1.0/samples/ 0000775 0000000 0000000 00000000000 13332436400 0014607 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/samples/memcpy/ 0000775 0000000 0000000 00000000000 13332436400 0016101 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/samples/memcpy/memcpy.c 0000664 0000000 0000000 00000041733 13332436400 0017547 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#define _DEFAULT_SOURCE
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "libocxl.h"
#define LOG_ERR(fmt, x...) fprintf(stderr, fmt, ##x)
#define LOG_INF(fmt, x...) printf(fmt, ##x)
#define AFU_NAME "IBM,MEMCPY3"
#define MEMCPY_SIZE 2048 // Max of 2048
#define CACHELINESIZE 128
/* Queue sizes other than 512kB don't seem to work (still true?) */
#define QUEUE_SIZE 4095*CACHELINESIZE
#define MEMCPY_WED(queue, depth) \
((((uint64_t)queue) & 0xfffffffffffff000ULL) | \
(((uint64_t)depth) & 0xfffULL))
#define MEMCPY_WE_CMD(valid, cmd) \
(((valid) & 0x1) | \
(((cmd) & 0x3f) << 2))
#define MEMCPY_WE_CMD_VALID (0x1 << 0)
#define MEMCPY_WE_CMD_WRAP (0x1 << 1)
#define MEMCPY_WE_CMD_COPY 0
#define MEMCPY_WE_CMD_IRQ 1
#define MEMCPY_WE_CMD_STOP 2
#define MEMCPY_WE_CMD_WAKE_HOST_THREAD 3
#define MEMCPY_WE_CMD_INCREMENT 4
#define MEMCPY_WE_CMD_ATOMIC 5
#define MEMCPY_WE_CMD_TRANSLATE_TOUCH 6
/* global mmio registers */
#define MEMCPY_AFU_GLOBAL_CFG 0
#define MEMCPY_AFU_GLOBAL_TRACE 0x20
/* per-process mmio registers */
#define MEMCPY_AFU_PP_WED 0
#define MEMCPY_AFU_PP_STATUS 0x10
#define MEMCPY_AFU_PP_STATUS_Terminated 0x8
#define MEMCPY_AFU_PP_STATUS_Stopped 0x10
#define MEMCPY_AFU_PP_CTRL 0x18
#define MEMCPY_AFU_PP_CTRL_Restart (0x1 << 0)
#define MEMCPY_AFU_PP_CTRL_Terminate (0x1 << 1)
#define MEMCPY_AFU_PP_IRQ 0x28
struct memcpy_work_element {
volatile uint8_t cmd; /* valid, wrap, cmd */
volatile uint8_t status;
union {
uint16_t length;
uint16_t tid;
};
uint8_t cmd_extra;
uint8_t reserved[3];
uint64_t atomic_op;
uint64_t src; /* also irq EA or atomic_op2 */
uint64_t dst;
} __packed;
struct memcpy_weq {
struct memcpy_work_element *queue;
struct memcpy_work_element *next;
struct memcpy_work_element *last;
int wrap;
int count;
};
int memcpy3_queue_length(size_t queue_size)
{
return queue_size/sizeof(struct memcpy_work_element);
}
void memcpy3_init_weq(struct memcpy_weq *weq, size_t queue_size)
{
weq->queue = aligned_alloc(getpagesize(), queue_size);
memset(weq->queue, 0, queue_size);
weq->next = weq->queue;
weq->last = weq->queue + memcpy3_queue_length(queue_size) - 1;
weq->wrap = 0;
weq->count = 0;
}
/*
* Copies a work element into the queue, taking care to set the wrap
* bit correctly. Returns a pointer to the element in the queue.
*
* @param weq the work element queue to populate
* @param we the work element
*/
struct memcpy_work_element *memcpy3_add_we(struct memcpy_weq *weq, struct memcpy_work_element *we)
{
struct memcpy_work_element *new_we = weq->next;
new_we->status = we->status;
new_we->length = we->length;
new_we->cmd_extra = we->cmd_extra;
new_we->atomic_op = we->atomic_op;
new_we->src = we->src;
new_we->dst = we->dst;
__sync_synchronize();
new_we->cmd = (we->cmd & ~MEMCPY_WE_CMD_WRAP) | weq->wrap;
weq->next++;
if (weq->next > weq->last) {
weq->wrap ^= MEMCPY_WE_CMD_WRAP;
weq->next = weq->queue;
}
return new_we;
}
/**
* Set up the Global MMIO area of the AFU
*
* @param afu the AFU handle
* @return false on success
*/
static bool global_setup(ocxl_afu_h afu)
{
uint64_t cfg;
ocxl_mmio_h global;
// Map the full global MMIO area of the AFU
if (OCXL_OK != ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global)) {
return true;
}
if (OCXL_OK != ocxl_mmio_read64(global, MEMCPY_AFU_GLOBAL_CFG, OCXL_MMIO_LITTLE_ENDIAN, &cfg)) {
LOG_ERR("Reading global config register failed\n");
return true;
}
LOG_INF("AFU config = 0x%lx\n", cfg);
uint64_t reg = 0x8008008000000000;
if (OCXL_OK != ocxl_mmio_write64(global, MEMCPY_AFU_GLOBAL_TRACE, OCXL_MMIO_LITTLE_ENDIAN, reg)) {
LOG_ERR("Writing trace register failed\n");
return true;
}
LOG_INF("traces reset and rearmed\n");
return 0;
}
/**
* Restart the AFU if it is stopped
*
* @param pp_mmio the per-PASID MMIO area of the AFU to restart
* @return false on success, true on failure
*/
static bool restart_afu_if_stopped(ocxl_mmio_h pp_mmio)
{
// Allow the AFU to proceed
if (OCXL_OK != ocxl_mmio_write64(pp_mmio, MEMCPY_AFU_PP_CTRL, OCXL_MMIO_LITTLE_ENDIAN, MEMCPY_AFU_PP_CTRL_Restart)) {
LOG_ERR("couldn't restart memcpy after interrupt\n");
return true;
}
return false;
}
/**
* Wait for a completion IRQ
*
* @param timeout the maximum amount of time to wait (seconds)
* @param afu the AFU that will be issuing the IRQ
* @param pp_mmio the per-PASID MMIO area of the AFU (or 0 if completion IRQ is not used)
* @param irq_ea the handle of the completion IRQ (or 0 if not used)
* @param err_ea the handle of the error IRQ
*
* @return a bitwise OR of issues detected
* 0x01: An AFU error was detected
* 0x02: A translation fault was received
* 0x04: An error occurred while accessing the AFU
* 0x08: A timeout occurred
*/
static int wait_for_irq(int timeout, ocxl_afu_h afu, ocxl_mmio_h pp_mmio, uint64_t irq_ea, uint64_t err_ea)
{
ocxl_event event;
int event_count;
int check_timeout = timeout * 1000; // convert to milliseconds
int ret = 0;
do {
event_count = ocxl_afu_event_check(afu, check_timeout, &event, 1);
if (event_count < 0) {
return 0x04;
}
if (event_count == 0) {
if (timeout) {
LOG_ERR("Timeout waiting for interrupt\n");
ret |= 0x08;
}
break;
}
// No need to wait if we go around the loop again
check_timeout = 0;
switch (event.type) {
case OCXL_EVENT_IRQ:
if (irq_ea && event.irq.handle == irq_ea) { // We have an AFU interrupt
LOG_INF("AFU completion interrupt received\n");
restart_afu_if_stopped(pp_mmio);
return 0; // Successfully got the completion interrupt & restarted the AFU
} else if (event.irq.handle == err_ea) { // We have an AFU error interrupt
LOG_ERR("AFU error interrupt received\n");
ret |= 0x01;
}
break;
case OCXL_EVENT_TRANSLATION_FAULT:
LOG_ERR("Translation fault detected, addr=%p count=%lu\n",
event.translation_fault.addr, event.translation_fault.count);
ret |= 0x02;
break;
}
} while (event_count == 1); // Go back around in case there are more events to process
return ret;
}
/**
* Wait for a completion bit to be set
*
* @param timeout the maximum amount of time to wait (seconds)
* @param work_element the work element to poll for completion
* @param afu the AFU that will be issuing the IRQ
* @param err_ea the handle of the error IRQ
*
* @return a bitwise OR of issues detected
* 0x01: An AFU error was detected
* 0x02: A translation fault was received
* 0x04: An error occurred while accessing the AFU
* 0x08: A timeout occurred
*/
static int wait_for_status(int timeout, ocxl_afu_h afu, struct memcpy_work_element *work_element, uint64_t err_ea)
{
struct timeval test_timeout, temp;
temp.tv_sec = timeout;
temp.tv_usec = 0;
gettimeofday(&test_timeout, NULL);
timeradd(&test_timeout, &temp, &test_timeout);
for (;; gettimeofday(&temp, NULL)) {
if (timercmp(&temp, &test_timeout, >)) {
LOG_ERR("timeout polling for completion\n");
return 0x08;
}
int ret = wait_for_irq(0, afu, 0, 0, err_ea);
if (ret) {
return ret;
}
if (work_element->status) {
break;
}
}
return 0;
}
#ifdef _ARCH_PPC64
/**
* Wait for wake_host_thread to be issued by the AFU
*
* @param timeout the maximum amount of time to wait (seconds)
* @param work_element the work element to poll for completion
* @param afu the AFU that will be issuing the IRQ
* @param pp_mmio the per-PASID MMIO area of the AFU
* @param irq_ea the handle of the completion IRQ
* @param err_ea the handle of the error IRQ
*
* @return a bitwise OR of issues detected
* 0x01: An AFU error was detected
* 0x02: A translation fault was received
* 0x04: An error occurred while accessing the AFU
* 0x08: A timeout occurred
*/
int wait_for_wake_host_thread(int timeout, ocxl_afu_h afu, ocxl_mmio_h pp_mmio,
struct memcpy_work_element *work_element, uint64_t irq_ea, uint64_t err_ea)
{
struct timeval test_timeout, temp;
temp.tv_sec = timeout;
temp.tv_usec = 0;
gettimeofday(&test_timeout, NULL);
timeradd(&test_timeout, &temp, &test_timeout);
for (;;) {
ocxl_wait();
if (work_element->status) {
return 0;
}
gettimeofday(&temp, NULL);
if (timercmp(&temp, &test_timeout, >)) {
LOG_ERR("timeout waiting for wake_host_thread\n");
break;
}
}
int ret = wait_for_irq(0, afu, pp_mmio, irq_ea, err_ea);
if (ret) {
return ret;
}
return 8;
}
#endif
/**
* Fill a buffer with data
*
* @param buf the buffer to fill
* @param size the size of the buffer
*/
static void fill_buffer(char *buf, size_t size)
{
/* Initialise source buffer */
for (size_t i = 0; i < size; i++) {
*(buf + i) = i & 0xff;
}
}
/**
* Display the status of the AFU
*
* @param pp_mmio the per-PASID MMIO area of the AFU context
*/
static void display_afu_status(ocxl_mmio_h pp_mmio)
{
uint64_t status = 0;
(void)ocxl_mmio_read64(pp_mmio, MEMCPY_AFU_PP_STATUS, OCXL_MMIO_LITTLE_ENDIAN, &status);
if (status) {
LOG_INF("AFU Status register is %lx\n", status);
}
}
/**
* Run a single memcpy operation
*
* @param afu the AFU to copy with
* @param src the data source
* @param dst where the dat should be copied to
* @param size the number of bytes to copy
* @param completion how to signal completion, 0 = poll, 1 = interrupt, 2 = notify/wait on Power9
* @param timeout the timeout in seconds to wait for completion
*
* @return false on success
*/
static bool afu_memcpy(ocxl_afu_h afu, const char *src, char *dst, size_t size, int completion, int timeout)
{
uint64_t wed;
struct memcpy_weq weq;
memcpy3_init_weq(&weq, QUEUE_SIZE);
// Point the work element descriptor (wed) at the work queue
wed = MEMCPY_WED(weq.queue, QUEUE_SIZE / CACHELINESIZE);
// Setup a work element in the queue
struct memcpy_work_element memcpy_we;
memset(&memcpy_we, 0, sizeof(memcpy_we));
memcpy_we.cmd = MEMCPY_WE_CMD(0, MEMCPY_WE_CMD_COPY);
memcpy_we.length = htole16((uint16_t) size);
memcpy_we.src = htole64((uintptr_t) src);
memcpy_we.dst = htole64((uintptr_t) dst);
LOG_INF("WED=0x%lx src=%p dst=%p size=%u\n", wed, src, dst, MEMCPY_SIZE);
if (OCXL_OK != ocxl_afu_attach(afu, OCXL_ATTACH_FLAGS_NONE)) {
goto err;
}
// Map the per-PASID MMIO space
ocxl_mmio_h pp_mmio;
if (OCXL_OK != ocxl_mmio_map(afu, OCXL_PER_PASID_MMIO, &pp_mmio)) {
goto err;
}
// Allocate an IRQ to report errors
ocxl_irq_h err_irq;
if (OCXL_OK != ocxl_irq_alloc(afu, NULL, &err_irq)) {
goto err;
}
// Let the AFU know the handle to trigger for errors
uint64_t err_irq_handle = ocxl_irq_get_handle(afu, err_irq);
if (OCXL_OK != ocxl_mmio_write64(pp_mmio, MEMCPY_AFU_PP_IRQ, OCXL_MMIO_LITTLE_ENDIAN, err_irq_handle)) {
goto err;
}
// Write the address of the work element descriptor to the AFU
if (OCXL_OK != ocxl_mmio_write64(pp_mmio, MEMCPY_AFU_PP_WED, OCXL_MMIO_LITTLE_ENDIAN, wed)) {
goto err;
}
// setup the work queue
struct memcpy_work_element *memcpy_element = memcpy3_add_we(&weq, &memcpy_we);
struct memcpy_work_element *irq_element = NULL;
struct memcpy_work_element *wake_element = NULL;
struct memcpy_work_element *stop_element = NULL;
ocxl_irq_h afu_irq;
uint64_t afu_irq_handle = 0;
if (completion == 1) {
// Set up the interrupt work element
// Allocate an IRQ to use for AFU notifications
if (OCXL_OK != ocxl_irq_alloc(afu, NULL, &afu_irq)) {
goto err;
}
// Insert the IRQ handle into a work element
afu_irq_handle = ocxl_irq_get_handle(afu, afu_irq);
struct memcpy_work_element irq_we;
memset(&irq_we, 0, sizeof(irq_we));
irq_we.cmd = MEMCPY_WE_CMD(1, MEMCPY_WE_CMD_IRQ);
irq_we.src = htole64(afu_irq_handle);
LOG_INF("irq EA = %lx\n", afu_irq_handle);
irq_element = memcpy3_add_we(&weq, &irq_we);
#ifdef _ARCH_PPC64
} else if (completion == 2) {
// Set up the wake_host_thread work element
// Allocate an IRQ to use for AFU notifications if wake_host_thread fails
if (OCXL_OK != ocxl_irq_alloc(afu, NULL, &afu_irq)) {
goto err;
}
afu_irq_handle = ocxl_irq_get_handle(afu, afu_irq);
uint16_t tid;
if (OCXL_OK != ocxl_afu_get_p9_thread_id(afu, &tid)) {
goto err;
}
struct memcpy_work_element wake_we;
memset(&wake_we, 0, sizeof(wake_we));
wake_we.cmd = MEMCPY_WE_CMD(1, MEMCPY_WE_CMD_WAKE_HOST_THREAD);
wake_we.src = htole64(afu_irq_handle);
wake_we.tid = htole16(tid);
wake_we.cmd_extra = 0x01;
LOG_INF("TID for wake_host_thread/wait = 0x%x\n", tid);
wake_element = memcpy3_add_we(&weq, &wake_we);
#endif
}
struct memcpy_work_element stop_we;
memset(&stop_we, 0, sizeof(stop_we));
stop_we.cmd = MEMCPY_WE_CMD(1, MEMCPY_WE_CMD_STOP);
stop_element = memcpy3_add_we(&weq, &stop_we);
// memory barrier to ensure the descriptor is written to memory before we ask the AFU to use it
__sync_synchronize();
// Initiate the memcpy
memcpy_element->cmd |= MEMCPY_WE_CMD_VALID;
/*
* wait for the AFU to be done
*
* if we're using an interrupt, we can go to sleep.
* Otherwise, we poll the last work element status from memory
*/
int rc = (completion == 1) ? wait_for_irq(timeout, afu, pp_mmio, afu_irq_handle, err_irq_handle) :
#ifdef _ARCH_PPC64
(completion == 2) ? wait_for_wake_host_thread(timeout, afu, pp_mmio, wake_element, afu_irq_handle, err_irq_handle) :
#endif
wait_for_status(timeout, afu, memcpy_element, err_irq_handle);
if (rc) {
goto err_status;
}
if (memcpy_element->status != 1) {
LOG_ERR("unexpected status 0x%x for copy\n", memcpy_element->status);
goto err_status;
}
if (completion == 1 && irq_element->status != 1) {
LOG_ERR("unexpected status 0x%x for IRQ\n", irq_element->status);
goto err_status;
}
if (completion == 2 && wake_element->status != 1) {
LOG_ERR("unexpected status 0x%x for wake\n", wake_element->status);
goto err_status;
}
wait_for_status(timeout, afu, stop_element, err_irq_handle);
if (stop_element->status != 1) {
LOG_ERR("unexpected status 0x%x for stop\n", stop_element->status);
goto err_status;
}
return 0;
err_status:
display_afu_status(pp_mmio);
goto err;
err:
return true;
}
static void usage(char *name)
{
fprintf(stderr, "Usage: %s [ options ]\n", name);
fprintf(stderr, "Options:\n");
fprintf(stderr,
"\t-i\t\tUse interrupts to indicate completion\n");
#ifdef _ARCH_PPC64
fprintf(stderr,
"\t-w\t\tUse wake_host_thread/wait to indicate completion\n");
#endif
fprintf(stderr,
"\t-t \tSeconds to wait for the AFU to signal completion\n");
fprintf(stderr,
"\t-v\t\tShow interactions with the AFU\n");
exit(1);
}
struct memcpy_test_args {
int completion; // 0 = Poll, 1 = IRQ, 2 = wake_host_thread/wait
bool verbose;
int completion_timeout;
};
int main(int argc, char *argv[])
{
struct memcpy_test_args args;
args.completion = 0;
args.completion_timeout = -1;
args.verbose = false;
while (1) {
int c = getopt(argc, argv, "+hs:it:v"
#ifdef _ARCH_PPC64
"w"
#endif
);
if (c < 0)
break;
switch (c) {
case '?':
case 'h':
usage(argv[0]);
break;
case 'i':
args.completion = 1;
break;
#ifdef _ARCH_PPC64
case 'w':
args.completion = 2;
break;
#endif
case 't':
args.completion_timeout = atoi(optarg);
break;
case 'v':
args.verbose = true;
break;
}
}
if (args.completion_timeout == -1) {
args.completion_timeout = 10;
}
if (argv[optind]) {
fprintf(stderr,
"Error: Unexpected argument '%s'\n", argv[optind]);
usage(argv[0]);
}
// Enable messages for open calls
if (args.verbose) {
ocxl_enable_messages(OCXL_ERRORS | OCXL_TRACING);
} else {
ocxl_enable_messages(OCXL_ERRORS);
}
ocxl_afu_h afu;
if (OCXL_OK != ocxl_afu_open(AFU_NAME, &afu)) {
LOG_ERR("Could not open AFU '%s'\n", AFU_NAME);
exit(1);
}
// Enable per-AFU messages
if (args.verbose) {
ocxl_afu_enable_messages(afu, OCXL_ERRORS | OCXL_TRACING);
} else {
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
}
if (global_setup(afu)) {
exit(1);
}
// Allocate memory areas for afu to copy to/from
char *src = aligned_alloc(64, MEMCPY_SIZE);
char *dst = aligned_alloc(64, MEMCPY_SIZE);
fill_buffer(src, MEMCPY_SIZE);
memset(dst, '\0', MEMCPY_SIZE);
if (afu_memcpy(afu, src, dst, MEMCPY_SIZE, args.completion, args.completion_timeout)) {
ocxl_afu_close(afu);
LOG_ERR("memcpy failed\n");
return 1;
}
if (memcmp(dst, src, MEMCPY_SIZE)) {
LOG_ERR("Memory contents do not match\n");
} else {
LOG_INF("Memory contents match\n");
}
ocxl_afu_close(afu);
return 0;
}
libocxl-1.1.0/src/ 0000775 0000000 0000000 00000000000 13332436400 0013732 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/src/afu.c 0000664 0000000 0000000 00000050421 13332436400 0014653 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libocxl_internal.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/**
* @defgroup ocxl_afu_getters OpenCAPI AFU Getters
*
* The AFU getter functions provide access to AFU metadata, such as the identifier,
* paths, and PASID.
*
* These operate on any valid AFU handle, even if it has not been opened.
*
* @{
*/
/**
* Get the PASID for the currently open context.
*
* While not commonly used, some AFU implementations may need their PASID written back
* to MMIO registers, or shared with other AFUs.
*
* @pre ocxl_afu_open() has been successfully called
* @param afu the AFU instance to get the PASID of
*
* @return the PASID
* @retval UINT32_MAX if the context has not been attached
*/
uint32_t ocxl_afu_get_pasid(ocxl_afu_h afu)
{
return afu->pasid;
}
/**
* Get the identifier of the AFU.
*
* The identifier contains the AFU name & index.
*
* @param afu The AFU to find the identifier of
*
* @return the identifier of the AFU
*/
const ocxl_identifier *ocxl_afu_get_identifier(ocxl_afu_h afu)
{
return &afu->identifier;
}
/**
* Get the canonical device path of the AFU.
*
* Returns the 'true' device path of the AFU from (within /dev), which may or may
* not be the same as the path passed to the library. It will differ when the specified
* path is a symlink or duplicate device.
*
* @param afu The AFU to get the device path of
*
* @return the device path, or NULL if the device is invalid
*/
const char *ocxl_afu_get_device_path(ocxl_afu_h afu)
{
return afu->device_path;
}
/**
* Get the canonical sysfs path of the AFU.
*
* Returns the 'true' sysfs path of the AFU (within /sys/class/ocxl).
*
* @param afu The AFU to get the sysfs path of
*
* @return the sysfs path, or NULL if the device is invalid
*/
const char *ocxl_afu_get_sysfs_path(ocxl_afu_h afu)
{
return afu->sysfs_path;
}
/**
* Get the version of the AFU.
*
* Returns the version of the AFU, as specified by the AFU implementation.
* See Section 4.3.3.1 AFU Descriptor Template 0 of the OpenCAPI Data Link Specification
* Offset 0x1C, AFU Version Major/Minor.
*
* @param afu The AFU to get the sysfs path of
* @param[out] major the major version number
* @param[out] minor the minor version number
*/
void ocxl_afu_get_version(ocxl_afu_h afu, uint8_t *major, uint8_t *minor)
{
*major = afu->version_major;
*minor = afu->version_minor;
}
/**
* @}
*
* @addtogroup ocxl_messages
*
* @{
*/
/**
* Enable messages from an AFU.
*
* Error messages, if enabled, are emitted by default on STDERR. This behavior may be
* overridden by ocxl_afu_set_error_message_handler().
*
* Tracing, if enabled, is always emitted on STDERR. It assists a developer by showing
* detailed AFU information, as well as MMIO & IRQ interactions between the application
* and the AFU. It does not show direct accesses to memory from the AFU.
*
* @see ocxl_afu_set_error_message_handler()
* @see ocxl_enable_messages()
*
* @param afu the AFU to enable message on
* @param sources a bitwise OR of the message sources to enable (OCXL_ERRORS, OCXL_TRACING)
*/
void ocxl_afu_enable_messages(ocxl_afu_h afu, uint64_t sources)
{
afu->verbose_errors = !!(sources & OCXL_ERRORS);
afu->tracing = !!(sources & OCXL_TRACING);
}
/**
* Override the default handler for emitting error messages for an AFU.
*
* The default error handler emits messages on STDERR, to override this behavior,
* pass a callback to this function.
*
* The callback is responsible for prefixing and line termination.
*
* Typical use cases would be redirecting error messages to the application's own
* logging/reporting mechanisms, and adding additional application-specific context
* to the error messages.
*
* @see ocxl_afu_enable_messages()
* @see ocxl_err_to_string()
*
* @param afu the AFU to override the error handler for
* @param handler the new error message handler
*/
void ocxl_afu_set_error_message_handler(ocxl_afu_h afu, void (*handler)(ocxl_afu_h afu, ocxl_err error,
const char *message))
{
afu->error_handler = handler;
}
/**
* @}
*
* @defgroup ocxl_afu OpenCAPI AFU Management
*
* These functions provide access to open and close the AFU.
*
* A typical workflow involves the following:
* - ocxl_afu_open_from_dev(), ocxl_afu_open() - Open the device by device or name
* - ocxl_afu_attach() - Attach the device to the process's address space
* - ocxl_mmio_map() - Map the MMIO space
*
* Subsequently, you will need to write information to the AFU's MMIO space (see ocxl_mmio)
* and also configure and handle interrupts (see ocxl_irq)
*
* Finally, to free the AFU handle, you can use ocxl_afu_close().
*
* @{
*/
/**
* @internal
*
* Initialize a new AFU structure.
*
* @param afu a pointer to the structure to initialize
*/
static void afu_init(ocxl_afu *afu)
{
memset((char *)afu->identifier.afu_name, '\0', sizeof(afu->identifier.afu_name));
afu->device_path = NULL;
afu->sysfs_path = NULL;
afu->version_major = 0;
afu->version_minor = 0;
afu->fd = -1;
afu->fd_info.type = EPOLL_SOURCE_OCXL;
afu->fd_info.irq = NULL;
afu->epoll_fd = -1;
afu->epoll_events = NULL;
afu->epoll_event_count = 0;
afu->global_mmio_fd = -1;
afu->global_mmio.start = NULL;
afu->global_mmio.length = 0;
afu->global_mmio.type = OCXL_GLOBAL_MMIO;
afu->per_pasid_mmio.start = NULL;
afu->per_pasid_mmio.length = 0;
afu->per_pasid_mmio.type = OCXL_PER_PASID_MMIO;
afu->page_size = sysconf(_SC_PAGESIZE);
afu->irqs = NULL;
afu->irq_count = 0;
afu->irq_max_count = 0;
afu->mmios = NULL;
afu->mmio_count = 0;
afu->mmio_max_count = 0;
afu->pasid = UINT32_MAX;
afu->verbose_errors = verbose_errors_all;
afu->error_handler = ocxl_default_afu_error_handler;
afu->tracing = tracing_all;
afu->attached = false;
#ifdef _ARCH_PPC64
afu->ppc64_amr = 0;
#endif
}
/**
* Allocate an AFU handle.
*
* On success, the handle should be freed with ocxl_afu_close().
*
* @param[out] afu_out a pointer to an AFU handle to set
*
* @retval OCXL_OK if the AFU was allocated
* @retval OCXL_NO_MEM if memory could not be allocated
*/
static ocxl_err afu_alloc(ocxl_afu_h *afu_out)
{
ocxl_afu *afu = malloc(sizeof(ocxl_afu));
if (afu == NULL) {
ocxl_err rc = OCXL_NO_MEM;
errmsg(NULL, rc, "Could not allocate %d bytes for AFU", sizeof(ocxl_afu));
return rc;
}
afu_init(afu);
*afu_out = afu;
return OCXL_OK;
}
/**
* Report if a device file in a directory points to the same device as dev.
*
* @param dirfd the fd of the directory to look in
* @param dev_name the name of the file
* @param dev the device to compare against
*
* @return true if the file & device represent the same device
*/
static bool device_matches(int dirfd, char *dev_name, dev_t dev)
{
struct stat sb;
if (fstatat(dirfd, dev_name, &sb, 0) == -1) {
return false;
}
if (!S_ISCHR(sb.st_mode)) {
return false;
}
return dev == sb.st_rdev;
}
/**
* Find the matching device for a given device major & minor, populate the AFU accordingly.
*
* @param dev the device number
* @param afu the afu to set the name & device paths
*
* @retval true if the device was found
*/
static bool populate_metadata(dev_t dev, ocxl_afu *afu)
{
DIR *dev_dir;
struct dirent *dev_ent;
dev_dir = opendir(DEVICE_PATH);
if (dev_dir == NULL) {
return false;
}
int fd = dirfd(dev_dir);
do {
if (!(dev_ent = readdir(dev_dir))) {
closedir(dev_dir);
return false;
}
} while (!device_matches(fd, dev_ent->d_name, dev));
closedir(dev_dir);
char *physical_function = strchr(dev_ent->d_name, '.');
if (physical_function == NULL) {
errmsg(NULL, OCXL_INTERNAL_ERROR, "Could not extract physical function from device name '%s', missing initial '.'",
dev_ent->d_name);
return false;
}
int afu_name_len = physical_function - dev_ent->d_name;
if (afu_name_len > AFU_NAME_MAX) {
errmsg(NULL, OCXL_INTERNAL_ERROR,"AFU name '%-.*s' exceeds maximum length of %d", afu_name_len, dev_ent->d_name);
return false;
}
physical_function++;
uint16_t domain;
uint8_t bus, device, function;
int found = sscanf(physical_function, "%hu:%hhu:%hhu.%hhu.%hhu",
&domain, &bus, &device, &function, &afu->identifier.afu_index);
if (found != 5) {
errmsg(NULL, OCXL_INTERNAL_ERROR, "Could not parse physical function '%s', only got %d components", physical_function,
found);
return false;
}
memcpy((char *)afu->identifier.afu_name, dev_ent->d_name, afu_name_len);
((char *)afu->identifier.afu_name)[afu_name_len] = '\0';
size_t dev_path_len = strlen(DEVICE_PATH) + 1 + strlen(dev_ent->d_name) + 1;
afu->device_path = malloc(dev_path_len);
if (NULL == afu->device_path) {
errmsg(NULL, OCXL_INTERNAL_ERROR, "Could not allocate %llu bytes for device path", dev_path_len);
return false;
}
(void)snprintf(afu->device_path, dev_path_len, "%s/%s", DEVICE_PATH, dev_ent->d_name);
size_t sysfs_path_len = strlen(SYS_PATH) + 1 + strlen(dev_ent->d_name) + 1;
afu->sysfs_path = malloc(sysfs_path_len);
if (NULL == afu->sysfs_path) {
errmsg(NULL, OCXL_INTERNAL_ERROR, "Could not allocate %llu bytes for sysfs path", sysfs_path_len);
return false;
}
(void)snprintf(afu->sysfs_path, sysfs_path_len, "%s/%s", SYS_PATH, dev_ent->d_name);
return true;
}
/**
* Output tracing information for AFU metadata.
*
* @param afu the AFU to display metadata for
*/
static void trace_metadata(ocxl_afu *afu)
{
TRACE_OPEN("device path=\"%s\"", afu->device_path);
TRACE_OPEN("sysfs path=\"%s\"", afu->sysfs_path);
TRACE_OPEN("AFU Name=\"%s\"", afu->identifier.afu_name);
TRACE_OPEN("AFU Index=%u", afu->identifier.afu_index);
TRACE_OPEN("AFU Version=%u:%u", afu->version_major, afu->version_minor);
TRACE_OPEN("Global MMIO size=%llu", afu->global_mmio.length);
TRACE_OPEN("Per PASID MMIO size=%llu", afu->per_pasid_mmio.length);
TRACE_OPEN("Page Size=%llu", afu->page_size);
TRACE_OPEN("PASID=%lu", afu->pasid);
}
/**
* Open a new context on an AFU.
*
* @param afu the AFU instance we want to open
*
* @retval OCXL_OK on success
* @retval OCXL_NO_DEV if the AFU is invalid
* @retval OCXL_ALREADY_DONE if the AFU is already open
* @retval OCXL_NO_MORE_CONTEXTS if maximum number of AFU contexts has been reached
*/
static ocxl_err afu_open(ocxl_afu *afu)
{
if (afu->fd != -1) {
return OCXL_ALREADY_DONE;
}
ocxl_err rc;
int fd = open(afu->device_path, O_RDWR | O_CLOEXEC | O_NONBLOCK);
if (fd < 0) {
if (errno == ENOSPC) {
rc = OCXL_NO_MORE_CONTEXTS;
errmsg(NULL, rc, "Could not open AFU device '%s', the maximum number of contexts has been reached: Error %d: %s",
afu->device_path, errno, strerror(errno));
return rc;
}
rc = OCXL_NO_DEV;
errmsg(NULL, rc, "Could not open AFU device '%s': Error %d: %s", afu->device_path, errno, strerror(errno));
return rc;
}
afu->fd = fd;
rc = global_mmio_open(afu);
if (rc != OCXL_OK) {
errmsg(NULL, rc, "Could not open global MMIO descriptor");
return rc;
}
fd = epoll_create1(EPOLL_CLOEXEC);
if (fd < 0) {
ocxl_err rc = OCXL_NO_DEV;
errmsg(NULL, rc, "Could not create epoll descriptor. Error %d: %s",
errno, strerror(errno));
return rc;
}
afu->epoll_fd = fd;
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = &afu->fd_info; // Already set up in afu_init
if (epoll_ctl(afu->epoll_fd, EPOLL_CTL_ADD, afu->fd, &ev) == -1) {
ocxl_err rc = OCXL_NO_DEV;
errmsg(NULL, rc, "Could not add device fd %d to epoll fd %d: %d: '%s'",
afu->fd, afu->epoll_fd, errno, strerror(errno));
return rc;
}
struct ocxl_ioctl_metadata metadata;
if (ioctl(afu->fd, OCXL_IOCTL_GET_METADATA, &metadata)) {
ocxl_err rc = OCXL_NO_DEV;
errmsg(NULL, rc, "OCXL_IOCTL_GET_METADATA failed %d:%s", errno, strerror(errno));
return rc;
}
// Metadata version 0, always available
afu->version_major = metadata.afu_version_major;
afu->version_minor = metadata.afu_version_minor;
afu->per_pasid_mmio.length = metadata.pp_mmio_size;
afu->global_mmio.length = metadata.global_mmio_size;
afu->pasid = metadata.pasid;
trace_metadata(afu);
return OCXL_OK;
}
/**
* Get an AFU instance at the specified device path.
*
* @param path the path of the AFU
* @param[out] afu the afu handle
*
* @retval OCXL_OK if we have successfully fetched the AFU
* @retval OCXL_NO_MEM if an out of memory error occurred
* @retval OCXL_NO_DEV if the device is invalid
*/
static ocxl_err get_afu_by_path(const char *path, ocxl_afu_h *afu)
{
ocxl_afu_h afu_h;
ocxl_err rc = afu_alloc(&afu_h);
if (rc != OCXL_OK)
goto err;
struct stat dev_stats;
if (stat(path, &dev_stats)) {
rc = OCXL_NO_DEV;
errmsg(NULL, rc, "Could not stat AFU device '%s': Error %d: %s", path, errno, strerror(errno));
goto err_free;
}
if (!populate_metadata(dev_stats.st_rdev, afu_h)) {
rc = OCXL_NO_DEV;
errmsg(NULL, rc, "Could not find OCXL device for '%s', major=%d, minor=%d, device expected in '%s'",
path, major(dev_stats.st_rdev), minor(dev_stats.st_rdev), DEVICE_PATH);
goto err_free;
}
*afu = afu_h;
return OCXL_OK;
err_free:
free(afu_h);
err:
*afu = OCXL_INVALID_AFU;
return rc;
}
/**
* Open an AFU context at a specified path.
*
* @param path the path of the AFU
* @param[out] afu the AFU handle which we will allocate. This should be freed with ocxl_afu_close
*
* @retval OCXL_OK if we have successfully fetched the AFU
* @retval OCXL_NO_MEM if an out of memory error occurred
* @retval OCXL_NO_DEV if the device is invalid
* @retval OCXL_NO_MORE_CONTEXTS if maximum number of AFU contexts has been reached
*/
ocxl_err ocxl_afu_open_from_dev(const char *path, ocxl_afu_h *afu)
{
libocxl_init();
ocxl_err rc = get_afu_by_path(path, afu);
if (rc != OCXL_OK) {
*afu = OCXL_INVALID_AFU;
return rc;
}
rc = afu_open((ocxl_afu *)*afu);
if (rc != OCXL_OK) {
ocxl_afu_close(*afu);
*afu = OCXL_INVALID_AFU;
return rc;
}
return OCXL_OK;
}
/**
* Open an AFU context with a specified name on a specific card/afu index.
*
* @param name the name of the AFU
* @param physical_function the PCI physical function of the card (as a string, or NULL for any)
* @param afu_index the AFU index (or -1 for any)
* @param[out] afu the AFU handle which we will allocate. This should be freed with ocxl_afu_close
*
* @retval OCXL_OK if we have successfully fetched the AFU
* @retval OCXL_NO_MEM if an out of memory error occurred
* @retval OCXL_NO_DEV if no valid device was found
* @retval OCXL_NO_MORE_CONTEXTS if maximum number of AFU contexts has been reached on all matching AFUs
*/
ocxl_err ocxl_afu_open_specific(const char *name, const char *physical_function, int16_t afu_index, ocxl_afu_h *afu)
{
char pattern[PATH_MAX];
glob_t glob_data;
ocxl_err ret = OCXL_INTERNAL_ERROR;
*afu = OCXL_INVALID_AFU;
libocxl_init();
if (afu_index == -1) {
snprintf(pattern, sizeof(pattern), "%s/%s.%s.*",
DEVICE_PATH, name,
physical_function ? physical_function : "*");
} else {
snprintf(pattern, sizeof(pattern), "%s/%s.%s.%d",
DEVICE_PATH, name,
physical_function ? physical_function : "*",
afu_index);
}
int rc = glob(pattern, GLOB_ERR, NULL, &glob_data);
switch (rc) {
case 0:
break;
case GLOB_NOSPACE:
ret = OCXL_NO_MEM;
errmsg(NULL, ret, "No memory for glob while listing AFUs");
goto end;
case GLOB_NOMATCH:
ret = OCXL_NO_DEV;
errmsg(NULL, ret, "No OCXL devices found in '%s' with pattern '%s'", DEVICE_PATH, pattern);
goto end;
default:
errmsg(NULL, ret, "Glob error %d while listing AFUs", rc);
goto end;
}
for (size_t dev = 0; dev < glob_data.gl_pathc; dev++) {
const char *dev_path = glob_data.gl_pathv[dev];
ret = ocxl_afu_open_from_dev(dev_path, afu);
switch (ret) {
case OCXL_OK:
goto end;
case OCXL_NO_MORE_CONTEXTS:
continue;
default:
goto end;
}
}
end:
globfree(&glob_data);
return ret;
}
/**
* Open an AFU context with a specified name.
*
* @param name the name of the AFU
* @param[out] afu the AFU handle which we will allocate. This should be freed with ocxl_afu_close
*
* @retval OCXL_OK if we have successfully fetched the AFU
* @retval OCXL_NO_MEM if an out of memory error occurred
* @retval OCXL_NO_DEV if no valid device was found
* @retval OCXL_NO_MORE_CONTEXTS if maximum number of AFU contexts has been reached on all matching AFUs
*/
ocxl_err ocxl_afu_open(const char *name, ocxl_afu_h *afu)
{
return ocxl_afu_open_specific(name, NULL, -1, afu);
}
/**
* Attach the calling process's memory to an open AFU context.
*
* An open AFU context is sufficient to configure the AFU, but in order for it to access
* application memory, the context must be attached to the current process.
*
* If specified, also sets the value of the PPC specific PSL AMR.
*
* @pre the AFU is opened
*
* @param afu the AFU to attach
* @param flags An ORed bitmask of flags
* OCXL_ATTACH_FLAGS_NONE accept the default behavior
*
* @retval OCXL_OK if the AFU was successful attached
* @retval OCXL_NO_CONTEXT if the AFU was not opened
* @retval OCXL_INTERNAL_ERROR if the AFU was unable to attach (check dmesg)
*/
ocxl_err ocxl_afu_attach(ocxl_afu_h afu, __attribute__((unused)) uint64_t flags)
{
if (afu->fd == -1) {
ocxl_err rc = OCXL_NO_CONTEXT;
errmsg(afu, rc, "Attempted to attach a closed AFU context");
return rc;
}
struct ocxl_ioctl_attach attach_args;
memset(&attach_args, '\0', sizeof(attach_args));
#ifdef _ARCH_PPC64
attach_args.amr = afu->ppc64_amr;
#endif
if (ioctl(afu->fd, OCXL_IOCTL_ATTACH, &attach_args)) {
ocxl_err rc = OCXL_INTERNAL_ERROR;
errmsg(afu, rc, "OCXL_IOCTL_ATTACH failed %d:%s", errno, strerror(errno));
return rc;
}
afu->attached = true;
return OCXL_OK;
}
/**
* Close an AFU and detach it from the context.
*
* This will free all resources allocated to the AFU, including MMIO areas and IRQs.
* The AFU handle may not be used after it is closed.
*
* @param afu a pointer to the AFU handle we want to close
*
* @retval OCXL_OK if the AFU was freed
* @retval OCXL_ALREADY_DONE if the AFU was not open
* @post All resources associated with the handle are closed and freed, the handle is no longer usable
*/
ocxl_err ocxl_afu_close(ocxl_afu_h afu)
{
if (afu->fd < 0) {
return OCXL_ALREADY_DONE;
}
for (uint16_t mmio_idx = 0; mmio_idx < afu->mmio_count; mmio_idx++) {
ocxl_mmio_unmap((ocxl_mmio_h)&afu->mmios[mmio_idx]);
}
if (afu->global_mmio_fd != -1) {
close(afu->global_mmio_fd);
afu->global_mmio_fd = -1;
}
if (afu->irqs) {
for (uint16_t irq = 0; irq < afu->irq_count; irq++) {
irq_dealloc(afu, &afu->irqs[irq]);
}
free(afu->irqs);
afu->irqs = NULL;
afu->irq_count = 0;
afu->irq_max_count = 0;
}
if (afu->epoll_events) {
free(afu->epoll_events);
afu->epoll_event_count = 0;
}
close(afu->epoll_fd);
afu->epoll_fd = -1;
close(afu->fd);
afu->fd = -1;
afu->attached = false;
if (afu->device_path) {
free(afu->device_path);
afu->device_path = NULL;
}
if (afu->sysfs_path) {
free(afu->sysfs_path);
afu->sysfs_path = NULL;
}
free(afu);
return OCXL_OK;
}
/**
* @}
*
* @defgroup ocxl_ppc OpenCAPI PowerPC specific functions
*
* Platform specific AFU functions for PowerPC
*
* @{
*/
#ifdef _ARCH_PPC64
/**
* Set the PPC64-specific PSL AMR register value for restricting access to the AFU.
*
* This register is documented in the Power ISA, Book III.
*
* This function is not available on other platforms.
*
* If used, this function should be called before ocxl_afu_attach()
*
* @param afu the AFU handle
* @param amr the AMR register value
* @retval OCXL_OK if the value was accepted
*/
ocxl_err ocxl_afu_set_ppc64_amr(ocxl_afu_h afu, uint64_t amr)
{
afu->ppc64_amr = amr;
return OCXL_OK;
}
#endif
/**
* @}
*/
libocxl-1.1.0/src/include/ 0000775 0000000 0000000 00000000000 13332436400 0015355 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/src/include/libocxl.h 0000664 0000000 0000000 00000025535 13332436400 0017174 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/**
* @file libocxl.h
* @brief library functions to implement userspace drivers for OpenCAPI accelerators
*
* Define LIBOCXL_LIVE_DANGEROUSLY before including this header to suppress optional
* compiler warnings, such as warnings on unused return values.
*/
#ifndef _LIBOCXL_H
#define _LIBOCXL_H
#include
#include
#include
#include
#include // Required for PROT_* for MMIO map calls
#include // Required for htobe32 & friends in MMIO access wrappers
#ifdef __cplusplus
extern "C" {
#endif
#define OCXL_NO_MESSAGES 0 /**< No messages requested */
#define OCXL_ERRORS (1 << 0) /**< Error messages requested */
#define OCXL_TRACING (1 << 1) /**< Tracing requested */
/**
* Defines the endianness of an AFU MMIO area
*/
typedef enum {
OCXL_MMIO_BIG_ENDIAN = 0, /**< AFU data is big-endian */
OCXL_MMIO_LITTLE_ENDIAN = 1, /**< AFU data is little-endian */
OCXL_MMIO_HOST_ENDIAN = 2, /**< AFU data is the same endianness as the host */
} ocxl_endian;
/**
* Defines the type of an MMIO area
*/
typedef enum {
OCXL_GLOBAL_MMIO,
OCXL_PER_PASID_MMIO
} ocxl_mmio_type;
#define AFU_NAME_MAX 24 /**< The maximum length of an AFU name */
/**
* AFU identification information
*/
typedef struct ocxl_identifier {
uint8_t afu_index; /**< The AFU Index */
const char afu_name[AFU_NAME_MAX + 1]; /**< The name of the AFU */
} ocxl_identifier;
/**
* A handle for an AFU
*/
typedef struct ocxl_afu *ocxl_afu_h;
#define OCXL_INVALID_AFU NULL /**< An invalid AFU handle */
/**
* A handle for an IRQ on an AFU
*/
typedef uint16_t ocxl_irq_h;
/**
* A handle for an MMIO region on an AFU
*/
typedef struct ocxl_mmio_area *ocxl_mmio_h;
/**
* Potential return values from ocxl_* functions
*/
typedef enum {
OCXL_OK = 0, /**< The call succeeded */
OCXL_NO_MEM = -1, /**< An out of memory error occurred */
OCXL_NO_DEV = -2, /**< The OpenCAPI device is not available */
OCXL_NO_CONTEXT = -3, /**< The call requires an open context on the AFU */
OCXL_NO_IRQ = -4, /**< no further interrupts are available, or the interrupt is invalid */
OCXL_INTERNAL_ERROR = -5, /**< an internal error has occurred */
OCXL_ALREADY_DONE = -6, /**< The action requested has already been performed */
OCXL_OUT_OF_BOUNDS = -7, /**< The action requested falls outside the permitted area */
OCXL_NO_MORE_CONTEXTS = -8, /**< No more contexts can be opened on the AFU */
OCXL_INVALID_ARGS = -9, /**< One or more arguments are invalid */
/* Adding something? Update setup.c: ocxl_err_to_string too */
} ocxl_err;
/**
* OCXL Event types
*/
typedef enum {
OCXL_EVENT_IRQ = 0, /**< An AFU IRQ */
OCXL_EVENT_TRANSLATION_FAULT = 1, /**< A memory translation fault occurred on the AFU */
} ocxl_event_type;
/**
* The data for a triggered IRQ event
*/
typedef struct {
uint16_t irq; /**< The IRQ number of the AFU */
uint64_t handle; /**< The 64 bit handle of the triggered IRQ */
void *info; /**< An opaque pointer associated with the IRQ */
uint64_t count; /**< The number of times the interrupt has been triggered since last checked */
} ocxl_event_irq;
/**
* The data for a triggered translation fault error event
*/
typedef struct {
void *addr; /**< The address that triggered the fault */
#ifdef _ARCH_PPC64
uint64_t dsisr; /**< The value of the PPC64 specific DSISR (Data storage interrupt status register) */
#endif
uint64_t count; /**< The number of times this address has triggered the fault */
} ocxl_event_translation_fault;
#ifndef _DOXYGEN_
#if defined(LIBOCXL_LIVE_DANGEROUSLY)
#define LIBOCXL_WARN_UNUSED
#elif defined(__clang__) && __clang_major__ < 3 || __clang_major__ == 3 && __clang_minor__ <= 8
#define LIBOCXL_WARN_UNUSED
#else
#define LIBOCXL_WARN_UNUSED __attribute__ ((warn_unused_result))
#endif
#endif /* _DOXYGEN_ */
/**
* An OCXL event
*
* This may be an AFU interrupt, or a translation error, as determined by ocxl_event.type.
*
* Once the type in known, the appropriate member of the anonymous union may be accessed.
*/
typedef struct ocxl_event {
ocxl_event_type type;
union {
ocxl_event_irq irq; /**< Usable only when the type is OCXL_EVENT_IRQ */
ocxl_event_translation_fault translation_fault; /**< Usable only when the type is OCXL_OCXL_EVENT_TRANSLATION_FAULT */
uint64_t padding[16];
};
} ocxl_event;
#define OCXL_ATTACH_FLAGS_NONE (0)
/* setup.c */
void ocxl_enable_messages(uint64_t sources);
void ocxl_set_error_message_handler(void (*handler)(ocxl_err error, const char *message));
const char *ocxl_err_to_string(ocxl_err err) LIBOCXL_WARN_UNUSED;
const char *ocxl_info() LIBOCXL_WARN_UNUSED;
/* afu.c */
/* AFU getters */
const ocxl_identifier *ocxl_afu_get_identifier(ocxl_afu_h afu) LIBOCXL_WARN_UNUSED;
const char *ocxl_afu_get_device_path(ocxl_afu_h afu) LIBOCXL_WARN_UNUSED;
const char *ocxl_afu_get_sysfs_path(ocxl_afu_h afu) LIBOCXL_WARN_UNUSED;
void ocxl_afu_get_version(ocxl_afu_h afu, uint8_t *major, uint8_t *minor);
uint32_t ocxl_afu_get_pasid(ocxl_afu_h afu) LIBOCXL_WARN_UNUSED;
/* AFU operations */
ocxl_err ocxl_afu_open_specific(const char *name, const char *physical_function, int16_t afu_index,
ocxl_afu_h *afu) LIBOCXL_WARN_UNUSED;
ocxl_err ocxl_afu_open_from_dev(const char *path, ocxl_afu_h *afu) LIBOCXL_WARN_UNUSED;
ocxl_err ocxl_afu_open(const char *name, ocxl_afu_h *afu) LIBOCXL_WARN_UNUSED;
void ocxl_afu_enable_messages(ocxl_afu_h afu, uint64_t sources);
void ocxl_afu_set_error_message_handler(ocxl_afu_h afu, void (*handler)(ocxl_afu_h afu, ocxl_err error,
const char *message));
ocxl_err ocxl_afu_close(ocxl_afu_h afu);
ocxl_err ocxl_afu_attach(ocxl_afu_h afu, uint64_t flags) LIBOCXL_WARN_UNUSED;
/* irq.c */
/* AFU IRQ functions */
ocxl_err ocxl_irq_alloc(ocxl_afu_h afu, void *info, ocxl_irq_h *irq_handle) LIBOCXL_WARN_UNUSED;
uint64_t ocxl_irq_get_handle(ocxl_afu_h afu, ocxl_irq_h irq) LIBOCXL_WARN_UNUSED;
int ocxl_afu_get_event_fd(ocxl_afu_h afu) LIBOCXL_WARN_UNUSED;
int ocxl_irq_get_fd(ocxl_afu_h afu, ocxl_irq_h irq) LIBOCXL_WARN_UNUSED;
int ocxl_afu_event_check_versioned(ocxl_afu_h afu, int timeout, ocxl_event *events, uint16_t event_count,
uint16_t event_api_version) LIBOCXL_WARN_UNUSED;
#ifdef _ARCH_PPC64
ocxl_err ocxl_afu_get_p9_thread_id(ocxl_afu_h afu, uint16_t *thread_id);
#endif
/**
* @addtogroup ocxl_irq
* @{
*/
#if defined(_ARCH_PPC64) && !defined(__STRICT_ANSI__)
/**
* A wrapper around the the POWER9 wait instruction
*
* The wake_host_thread/wait mechanism provide a low-latency way for an AFU to signal to the
* calling thread that a condition has been met (eg. work has been completed).
*
* This function will cause the thread to wait until woken by the AFU via wake_host_thread.
* As the thread may be woken for reasons other than wake_host_thread, a condition variable
* must be set by the AFU before issuing the wake.
*
* In order to successfully wake a waiting thread, the AFU must know the address of
* the condition variable, and the thread ID of the application (via ocxl_afu_get_p9_thread_id()).
*
* A typical usage will be:
* @code
* while (!condition_variable_is_set()) {
* ocxl_wait();
* } // Pause execution until the condition variable is set
*
* clear_condition_variable();
*
* // Execution continues here
* @endcode
*
* @see ocxl_afu_get_p9_thread_id()
*/
#ifndef _DOXYGEN_
static
#endif
inline void ocxl_wait()
{
/* This would be just 'asm volatile ("wait")', but clang produces invalid machine code */
asm volatile (".long 0x7c00003c");
}
#elif defined(_ARCH_PPC64) && !defined(LIBOCXL_SUPPRESS_INACCESSIBLE_WARNINGS)
#warning LibOCXL ocxl_wait() will not be available while ANSI C mode is enabled
#endif
/**
* Check for pending IRQs and other events.
*
* Waits for the AFU to report an event or IRQs. On return, events will be populated
* with the reported number of events. Each event may be either an AFU event, or an IRQ,
* which can be determined by checking the value of events[i].type:
* Value | Action
* ------------------------------ | -------
* OCXL_EVENT_IRQ | An IRQ was triggered, and events[i].irq is populated with the IRQ information identifying which IRQ was triggered
* OCXL_EVENT_TRANSLATION_FAULT | An OpenCAPI translation fault error has been issued, that is, the system has been unable to resolve an effective address. Events[i].translation_fault will be populated with the details of the error
*
* @param afu the AFU holding the interrupts
* @param timeout how long to wait (in milliseconds) for interrupts to arrive, set to -1 to wait indefinitely, or 0 to return immediately if no events are available
* @param[out] events the triggered events (caller allocated)
* @param event_count the number of triggered events
*
* @return the number of events triggered, if this is the same as event_count, you should call ocxl_afu_event_check again
* @retval -1 if an error occurred
*/
LIBOCXL_WARN_UNUSED
#ifndef _DOXYGEN_
static
#endif
inline int ocxl_afu_event_check(ocxl_afu_h afu, int timeout, ocxl_event *events, uint16_t event_count)
{
uint16_t event_api_version = 0;
return ocxl_afu_event_check_versioned(afu, timeout, events, event_count, event_api_version);
}
/**
* @}
*/
/* Platform specific: PPC64 */
#ifdef _ARCH_PPC64
ocxl_err ocxl_afu_set_ppc64_amr(ocxl_afu_h afu, uint64_t amr);
#endif
/* mmio.c */
ocxl_err ocxl_mmio_map_advanced(ocxl_afu_h afu, ocxl_mmio_type type, size_t size, int prot, uint64_t flags,
off_t offset, ocxl_mmio_h *region) LIBOCXL_WARN_UNUSED;
ocxl_err ocxl_mmio_map(ocxl_afu_h afu, ocxl_mmio_type type, ocxl_mmio_h *region) LIBOCXL_WARN_UNUSED;
void ocxl_mmio_unmap(ocxl_mmio_h region);
int ocxl_mmio_get_fd(ocxl_afu_h afu, ocxl_mmio_type type) LIBOCXL_WARN_UNUSED;
size_t ocxl_mmio_size(ocxl_afu_h afu, ocxl_mmio_type type) LIBOCXL_WARN_UNUSED;
ocxl_err ocxl_mmio_get_info(ocxl_mmio_h region, void **address, size_t *size);
ocxl_err ocxl_mmio_read32(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint32_t *out);
ocxl_err ocxl_mmio_read64(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint64_t *out);
ocxl_err ocxl_mmio_write32(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint32_t value);
ocxl_err ocxl_mmio_write64(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint64_t value);
#ifdef __cplusplus
}
#endif
#endif /* _LIBOCXL_H */
libocxl-1.1.0/src/internal.c 0000664 0000000 0000000 00000013021 13332436400 0015707 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libocxl_internal.h"
#include "libocxl_info.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
/// The base sysfs path for OCXL devices
const char *sys_path = NULL;
/// The base device path for OCXL devices
const char *dev_path = NULL;
bool libocxl_inited = false;
pthread_mutex_t libocxl_inited_mutex = PTHREAD_MUTEX_INITIALIZER;
bool verbose_errors = false;
bool verbose_errors_all = false;
bool tracing = false;
bool tracing_all = false;
void ocxl_default_error_handler(ocxl_err error, const char *message);
void (*error_handler)(ocxl_err error, const char *message) = ocxl_default_error_handler;
pthread_mutex_t stderr_mutex = PTHREAD_MUTEX_INITIALIZER;
/**
* Executed on first afu_open
* - Check the LIBOCXL_INFO environment variable and output the info string
* - Check the LIBOCXL_TRACE_ALL environment variable and enable tracing_all
* - Check the LIBOCXL_VERBOSE_ERRORS_ALL environment variable and enable verbose_errors_all
*/
void libocxl_init()
{
const char *val;
pthread_mutex_lock(&libocxl_inited_mutex);
if (libocxl_inited) {
pthread_mutex_unlock(&libocxl_inited_mutex);
return;
}
val = getenv("LIBOCXL_INFO");
if (val && (!strcasecmp(val, "yes") || !strcmp(val, "1"))) {
fprintf(stderr, "%s\n", libocxl_info);
}
val = getenv("LIBOCXL_TRACE_ALL");
if (val && (!strcasecmp(val, "yes") || !strcmp(val, "1"))) {
tracing_all = true;
tracing = true;
}
val = getenv("LIBOCXL_VERBOSE_ERRORS_ALL");
if (val && (!strcasecmp(val, "yes") || !strcmp(val, "1"))) {
verbose_errors_all = true;
verbose_errors = true;
}
libocxl_inited = true;
pthread_mutex_unlock(&libocxl_inited_mutex);
}
/**
* Output a trace message
* @param file the source filename
* @param line the source line
* @param function the function name
* @param label the label for the message
* @param format a printf format & args
*/
__attribute__ ((format (printf, 5, 6)))
void trace_message(const char *label, const char *file, int line,
const char *function, const char *format, ...)
{
va_list ap;
va_start(ap, format);
pthread_mutex_lock(&stderr_mutex);
fprintf(stderr, "%s: %s:%d\t%s():\t\t", label, file, line, function);
vfprintf(stderr, format, ap);
fprintf(stderr, "\n");
pthread_mutex_unlock(&stderr_mutex);
va_end(ap);
}
#define MAX_MESSAGE_LENGTH 255
/**
* Output an error message
* @param afu the AFU the error message originated from, or NULL if there was none
* @param error the error value associated with this message
* @param format a printf format & args
*/
__attribute__ ((format (printf, 3, 4)))
void errmsg(ocxl_afu *afu, ocxl_err error, const char *format, ...)
{
va_list ap;
va_start(ap, format);
if (afu) {
if (afu->verbose_errors) {
char buf[MAX_MESSAGE_LENGTH];
vsnprintf(buf, sizeof(buf), format, ap);
buf[sizeof(buf) - 1] = '\0';
ocxl_afu_h afu_handle = (ocxl_afu_h) afu;
afu->error_handler(afu_handle, error, buf);
}
} else {
if (verbose_errors) {
char buf[MAX_MESSAGE_LENGTH];
vsnprintf(buf, sizeof(buf), format, ap);
buf[sizeof(buf) - 1] = '\0';
error_handler(error, buf);
}
}
va_end(ap);
}
/**
* Print an error message on stderr
* @param error the error value
* @param message the message
*/
void ocxl_default_error_handler(ocxl_err error, const char *message)
{
pthread_mutex_lock(&stderr_mutex);
fprintf(stderr, "ERROR: %s: %s\n", ocxl_err_to_string(error), message);
pthread_mutex_unlock(&stderr_mutex);
}
/**
* Print an error message on stderr
* @param afu the AFU the error message originated from
* @param error the error value
* @param message the message
*/
void ocxl_default_afu_error_handler(ocxl_afu_h afu, ocxl_err error, const char *message)
{
const char *dev = ocxl_afu_get_device_path(afu);
pthread_mutex_lock(&stderr_mutex);
fprintf(stderr, "ERROR: %s\t%s: %s\n", dev ? dev : "No AFU", ocxl_err_to_string(error), message);
pthread_mutex_unlock(&stderr_mutex);
}
/**
* Grow a buffer geometrically
*
* @param afu the AFU that owns the buffer
* @param buffer [in,out] the buffer to grow
* @param [in,out] count the number of elements in the buffer
* @param size the size of a buffer element
* @param initial_count the initial number of elements in the buffer
*/
ocxl_err grow_buffer(ocxl_afu *afu, void **buffer, uint16_t *count, size_t size, size_t initial_count)
{
size_t new_count = (*count > 0) ? 2 * *count : initial_count;
void *temp = realloc(*buffer, new_count * size);
if (temp == NULL) {
ocxl_err rc = OCXL_NO_MEM;
errmsg(afu, rc, "Could not realloc buffer to %lu elements of %lu bytes (%lu bytes total): %d '%s'",
new_count, size, new_count * size, errno, strerror(errno));
return rc;
}
memset((char *)temp + *count * size, '\0', new_count - *count);
*buffer = temp;
*count = new_count;
return OCXL_OK;
}
libocxl-1.1.0/src/irq.c 0000664 0000000 0000000 00000041302 13332436400 0014671 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libocxl_internal.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define MAX_EVENT_SIZE (16*sizeof(uint64_t))
/**
* Deallocate a single IRQ.
*
* @param afu the AFU the IRQ belongs to
* @param irq the IRQ
*/
void irq_dealloc(ocxl_afu *afu, ocxl_irq *irq)
{
if (irq->addr) {
if (munmap(irq->addr, afu->page_size)) {
errmsg(afu, OCXL_INTERNAL_ERROR, "Could not unmap IRQ page: %d: '%s'",
errno, strerror(errno));
}
irq->addr = NULL;
}
if (irq->event.irq_offset) {
int rc = ioctl(afu->fd, OCXL_IOCTL_IRQ_FREE, &irq->event.irq_offset);
if (rc) {
errmsg(afu, OCXL_INTERNAL_ERROR, "Could not free IRQ in kernel: %d", rc);
}
irq->event.irq_offset = 0;
}
if (irq->event.eventfd >= 0) {
close(irq->event.eventfd);
irq->event.eventfd = -1;
}
irq->info = NULL;
}
/**
* @defgroup ocxl_irq OpenCAPI IRQ, Event & Wake Functions
*
* These functions allow the allocation and handling of AFU IRQs, OpenCAPI events, and wakes.
* IRQs can be handled either via requesting an array of triggered IRQ handles (via ocxl_afu_check),
* or by issuing callbacks via ocxl_afu_handle_callbacks().
*
* Each IRQ has an opaque pointer attached, which is communicated to the caller via the event struct
* passed back from ocxl_afu_event_check(). This pointer can be used by the caller to
* save identifying information against the IRQ.
*
* @{
*/
/**
* Allocate a single IRQ
*
* @param afu the AFU to operate on
* @param irq the IRQ struct to populate
* @param info user information to associate with the handle (may be NULL)
*
* @retval OCXL_OK if the IRQ was allocated
* @retval OCXL_INTERNAL_ERROR if an error occurred allocating the IRQ
* @retval OCXL_NO_MEM if an out of memory error occurred
*/
static ocxl_err irq_allocate(ocxl_afu *afu, ocxl_irq *irq, void *info)
{
irq->event.irq_offset = 0;
irq->event.eventfd = -1;
irq->event.reserved = 0;
irq->irq_number = UINT16_MAX;
irq->addr = NULL;
irq->info = info;
irq->fd_info.type = EPOLL_SOURCE_IRQ;
irq->fd_info.irq = irq;
ocxl_err ret = OCXL_INTERNAL_ERROR;
int fd = eventfd(0, EFD_CLOEXEC);
if (fd < 0) {
errmsg(afu, ret, "Could not open eventfd : %d: '%s'", errno, strerror(errno));
goto errend;
}
irq->event.eventfd = fd;
int rc = ioctl(afu->fd, OCXL_IOCTL_IRQ_ALLOC, &irq->event.irq_offset);
if (rc) {
errmsg(afu, ret, "Could not allocate IRQ in kernel: %d", rc);
goto errend;
}
rc = ioctl(afu->fd, OCXL_IOCTL_IRQ_SET_FD, &irq->event);
if (rc) {
errmsg(afu, ret, "Could not set event descriptor in kernel: %d", rc);
goto errend;
}
irq->addr = mmap(NULL, afu->page_size, PROT_WRITE, MAP_SHARED,
afu->fd, irq->event.irq_offset);
if (irq->addr == MAP_FAILED) {
errmsg(afu, ret, "mmap for IRQ failed: %d: '%s'", errno, strerror(errno));
goto errend;
}
struct epoll_event ev;
ev.events = EPOLLIN;
ev.data.ptr = &irq->fd_info;
if (epoll_ctl(afu->epoll_fd, EPOLL_CTL_ADD, irq->event.eventfd, &ev) == -1) {
errmsg(afu, ret, "Could not add IRQ fd %d to epoll fd %d: %d: '%s'",
irq->event.eventfd, afu->epoll_fd, errno, strerror(errno));
goto errend;
}
return OCXL_OK;
errend:
irq_dealloc(afu, irq);
return ret;
}
/**
* Allocate an IRQ for an open AFU.
*
* Once allocated, the IRQ handle can be retrieved with ocxl_irq_get_handle(),
* and written into an AFU specific register in the AFU's MMIO area. The AFU
* can then trigger the IRQ, which can be listened for with ocxl_afu_event_check(),
* or by obtaining an event descriptor via ocxl_irq_get_fd() and using it with
* poll(), select(), etc.
*
* @param afu the AFU to allocate IRQs for
* @param info user information to associate with the handle (may be NULL)
* @param[out] irq the 0 indexed IRQ number that was allocated. This will be monotonically incremented by each subsequent call.
*
* @retval OCXL_OK if the IRQs have been allocated
* @retval OCXL_NO_MEM if a memory allocation error occurred
*/
ocxl_err ocxl_irq_alloc(ocxl_afu_h afu, void *info, ocxl_irq_h *irq)
{
if (afu->irq_count == afu->irq_max_count) {
ocxl_err rc = grow_buffer(afu, (void **)&afu->irqs, &afu->irq_max_count, sizeof(ocxl_irq), INITIAL_IRQ_COUNT);
if (rc != OCXL_OK) {
errmsg(afu, rc, "Could not grow IRQ buffer");
return rc;
}
}
ocxl_err rc = irq_allocate(afu, &afu->irqs[afu->irq_count], info);
if (rc != OCXL_OK) {
errmsg(afu, rc, "Could not allocate IRQ");
return rc;
}
afu->irqs[afu->irq_count].irq_number = afu->irq_count;
*irq = (ocxl_irq_h)afu->irq_count;
afu->irq_count++;
return OCXL_OK;
}
/**
* Get the 64 bit IRQ handle for an IRQ.
*
* This handle can be written to the AFU's MMIO area to allow the AFU to trigger the IRQ.
*
* @param afu the AFU the IRQ belongs to
* @param irq the IRQ to get the handle of
*
* @return the handle, or 0 if the handle is invalid
*/
uint64_t ocxl_irq_get_handle(ocxl_afu_h afu, ocxl_irq_h irq)
{
if (irq > afu->irq_count) {
return 0;
}
return (uint64_t)afu->irqs[irq].addr;
}
/**
* Get the file descriptor associated with an IRQ.
*
* This descriptor may be used with select/poll to determine if an IRQ is triggered.
*
* @param afu the AFU the IRQ belongs to
* @param irq the IRQ to get the descriptor of
*
* @return the handle, or -1 if the descriptor is invalid
*/
int ocxl_irq_get_fd(ocxl_afu_h afu, ocxl_irq_h irq)
{
if (irq > afu->irq_count) {
return -1;
}
return afu->irqs[irq].event.eventfd;
}
/**
* Get a descriptor that will trigger a poll when an AFU event occurs.
*
* When triggered, call ocxl_read_afu_event() to extract the event information.
*
* @see ocxl_afu_event_check()
*
* @pre the AFU has been opened
*
* @param afu the AFU the IRQ belongs to
*
* @return the handle
*/
int ocxl_afu_get_event_fd(ocxl_afu_h afu)
{
return afu->fd;
}
typedef struct ocxl_kernel_event_header ocxl_kernel_event_header;
typedef struct ocxl_kernel_event_xsl_fault_error ocxl_kernel_event_xsl_fault_error;
/**
* @internal
*
* Populate an XSL fault error event.
*
* @param event the event to populate
* @param body the event body from the kernel
*/
static void populate_xsl_fault_error(ocxl_afu *afu, ocxl_event *event, void *body)
{
ocxl_kernel_event_xsl_fault_error *err = body;
event->type = OCXL_EVENT_TRANSLATION_FAULT;
event->translation_fault.addr = (void *)err->addr;
#ifdef _ARCH_PPC64
event->translation_fault.dsisr = err->dsisr;
TRACE(afu, "Translation fault error received, addr=%p, dsisr=%llx, count=%llu",
event->translation_fault.addr, event->translation_fault.dsisr, err->count);
#else
TRACE(afu, "Translation fault error received, addr=%p, count=%llu",
event->translation_fault.addr, err->count);
#endif
event->translation_fault.count = err->count;
}
/**
* @internal
*
* Read a single AFU event from the main AFU descriptor.
*
* This function should not be called directly, instead, use the ocxl_read_afu_event()
* wrapper.
*
* An AFU may report OpenCAPI events independently from it's IRQs. When an event is
* available, as notified by the descriptor returned by ocxl_afu_get_event_fd()
* triggering a poll() or select(), this function will extract the information
* and notify the caller if there are any further events to be queried.
*
* If an event is available and should be handled by the caller,
* OCXL_EVENT_ACTION_SUCCESS is returned, and the event struct populated. The event struct
* should be parsed by first checking the type:
* Value | Action
* ------------------------------ | -------
* OCXL_EVENT_IRQ | This value cannot be generated by this function
* OCXL_EVENT_TRANSLATION_FAULT | An OpenCAPI translation fault error has been issued, that is, the system has been unable to resolve an effective address. Events[i].translation_fault will be populated with the details of the error
*
* @see ocxl_read_afu_event()
*
* @param afu the AFU to read the event from
* @param event_api_version the version of the event API that the caller wants to see
* @param[out] event event to populate
* @param[out] last true if this was the last event to read from the kernel for now
*
* @retval OCXL_EVENT_ACTION_SUCCESS if the event should be handled
* @retval OCXL_EVENT_ACTION_FAIL if the event read failed (fatal)
* @retval OCXL_EVENT_ACTION_NONE if there was no event to read
* @retval OCXL_EVENT_ACTION_IGNORE if the read was successful but should be ignored
*/
static ocxl_event_action read_afu_event(ocxl_afu_h afu, uint16_t event_api_version, ocxl_event *event, int *last)
{
size_t event_size = sizeof(ocxl_kernel_event_header);
*last = 0;
uint16_t max_supported_event = 0;
switch (event_api_version) {
case 0:
event_size += sizeof(ocxl_kernel_event_xsl_fault_error);
max_supported_event = OCXL_AFU_EVENT_XSL_FAULT_ERROR;
break;
default:
errmsg(afu, OCXL_INTERNAL_ERROR, "Unsupported event API version %u, your libocxl library may be too old",
event_api_version);
return OCXL_EVENT_ACTION_FAIL;
}
char buf[event_size];
ssize_t buf_used;
if ((buf_used = read(afu->fd, buf, event_size)) < 0) {
if (errno == EAGAIN || errno == EWOULDBLOCK) {
*last = 1;
return OCXL_EVENT_ACTION_NONE;
}
errmsg(afu, OCXL_INTERNAL_ERROR, "read of event header from fd %d failed: %d: %s",
afu->fd, errno, strerror(errno));
return OCXL_EVENT_ACTION_FAIL;
} else if (buf_used < (ssize_t)sizeof(ocxl_kernel_event_header)) {
errmsg(afu, OCXL_INTERNAL_ERROR, "short read of event header from fd %d", afu->fd);
return OCXL_EVENT_ACTION_FAIL;
}
ocxl_kernel_event_header *header = (ocxl_kernel_event_header *)buf;
if (header->type > max_supported_event) {
TRACE(afu, "Unknown event received from kernel of type %u", header->type);
*last = !! (header->flags & OCXL_KERNEL_EVENT_FLAG_LAST);
return OCXL_EVENT_ACTION_IGNORE;
}
switch (header->type) {
case OCXL_AFU_EVENT_XSL_FAULT_ERROR:
if (buf_used != sizeof(ocxl_kernel_event_header) + sizeof(ocxl_kernel_event_xsl_fault_error)) {
errmsg(afu, OCXL_INTERNAL_ERROR,
"Incorrectly sized buffer received from kernel for XSL fault error, expected %d, got %d",
sizeof(ocxl_kernel_event_header) + sizeof(ocxl_kernel_event_xsl_fault_error),
buf_used);
return OCXL_EVENT_ACTION_FAIL;
}
populate_xsl_fault_error(afu, event, buf + sizeof(ocxl_kernel_event_header));
break;
default:
errmsg(afu, OCXL_INTERNAL_ERROR, "Unknown event %d, max_supported_event %d",
header->type, max_supported_event);
return OCXL_EVENT_ACTION_FAIL;
}
*last = !! (header->flags & OCXL_KERNEL_EVENT_FLAG_LAST);
return OCXL_EVENT_ACTION_SUCCESS;
}
/**
* Check for pending IRQs and other events.
*
* This function should not be called directly, instead, use the ocxl_afu_event_check()
* wrapper.
*
* Waits for the AFU to report an event or IRQs. On return, events will be populated
* with the reported number of events. Each event may be either an AFU event, or an IRQ,
* which can be determined by checking the value of events[i].type:
* Value | Action
* ------------------------------ | -------
* OCXL_EVENT_IRQ | An IRQ was triggered, and events[i].irq is populated with the IRQ information identifying which IRQ was triggered
* OCXL_EVENT_TRANSLATION_FAULT | An OpenCAPI translation fault error has been issued, that is, the system has been unable to resolve an effective address. Events[i].translation_fault will be populated with the details of the error
*
* @see ocxl_afu_event_check
*
* @param afu the AFU holding the interrupts
* @param timeout how long to wait (in milliseconds) for interrupts to arrive, set to -1 to wait indefinitely, or 0 to return immediately if no events are available
* @param[out] events the triggered events (caller allocated)
* @param event_count the number of events that can fit into the events array
* @param event_api_version the version of the event API that the caller wants to see
*
* @return the number of events triggered, if this is the same as event_count, you should call ocxl_afu_event_check again
* @retval -1 if an error occurred
*/
int ocxl_afu_event_check_versioned(ocxl_afu_h afu, int timeout, ocxl_event *events, uint16_t event_count,
uint16_t event_api_version)
{
TRACE(afu, "Waiting up to %dms for AFU events", timeout);
if (event_count > afu->epoll_event_count) {
free(afu->epoll_events);
afu->epoll_events = NULL;
afu->epoll_event_count = 0;
struct epoll_event *events = malloc(event_count * sizeof(*events));
if (events == NULL) {
errmsg(afu, OCXL_NO_MEM, "Could not allocate space for %d events", event_count);
return -1;
}
afu->epoll_events = events;
afu->epoll_event_count = event_count;
}
int count;
if ((count = epoll_wait(afu->epoll_fd, afu->epoll_events, event_count, timeout)) == -1) {
errmsg(afu, OCXL_INTERNAL_ERROR, "epoll_wait failed waiting for AFU events: %d: '%s'",
errno, strerror(errno));
return -1;
}
uint16_t triggered = 0;
for (int event = 0; event < count; event++) {
epoll_fd_source *info = (epoll_fd_source *)afu->epoll_events[event].data.ptr;
ocxl_event_action ret;
ssize_t buf_used;
uint64_t count;
int last;
switch (info->type) {
case EPOLL_SOURCE_OCXL:
while ((ret = read_afu_event(afu, event_api_version, &events[triggered], &last)),
ret == OCXL_EVENT_ACTION_SUCCESS || ret == OCXL_EVENT_ACTION_IGNORE) {
if (ret == OCXL_EVENT_ACTION_SUCCESS) {
triggered++;
}
if (last) {
break;
}
}
if (ret == OCXL_EVENT_ACTION_FAIL) {
return -1;
}
break;
case EPOLL_SOURCE_IRQ:
buf_used = read(info->irq->event.eventfd, &count, sizeof(count));
if (buf_used < 0) {
errmsg(afu, OCXL_INTERNAL_ERROR, "read of eventfd %d IRQ %d failed: %d: %s",
info->irq->event.eventfd, info->irq->irq_number, errno, strerror(errno));
continue;
} else if (buf_used != (ssize_t)sizeof(count)) {
errmsg(afu, OCXL_INTERNAL_ERROR, "short read of eventfd %d IRQ %d");
continue;
}
events[triggered].type = OCXL_EVENT_IRQ;
events[triggered].irq.irq = info->irq->irq_number;
events[triggered].irq.handle = (uint64_t)info->irq->addr;
events[triggered].irq.info = info->irq->info;
events[triggered++].irq.count = count;
TRACE(afu, "IRQ received, irq=%u id=%llx info=%p count=%llu",
info->irq->irq_number, (uint64_t)info->irq->addr, info->irq->info, count);
break;
}
}
TRACE(afu, "%u events reported", triggered);
return triggered;
}
/**
* Get the thread ID required to wake up a Power 9 wait instruction
*
* The thread ID should be provided to the AFU, along with a condition variable to
* indicate a true wake condition.
*
* Note that multiple AFU contexts within the same thread will share the same thread ID.
* Thread IDs are cached within a context, and are requested from the kernel the first time
* this function is called for an AFU context.
*
* If sharing AFU contexts between threads, the thread ID should be requested only in the thread
* that will be waiting for the AFU context.
*
* @param afu the AFU to get the thread ID for
* @param[out] thread_id the thread ID
* @retval OCXL_OK if the thread ID was retrieved successfully
* @retval OCXL_NO_DEV if the OpenCAPI device is not capable of Power 9 notify/wake
*
* @see ocxl_wait()
*/
ocxl_err ocxl_afu_get_p9_thread_id(ocxl_afu_h afu, uint16_t *thread_id)
{
ocxl_afu *my_afu = (ocxl_afu *)afu;
struct ocxl_ioctl_features features;
int rc = ioctl(my_afu->fd, OCXL_IOCTL_GET_FEATURES, &features);
if (rc) {
errmsg(afu, OCXL_NO_DEV, "Could not identify platform: %d %s",
errno, strerror(errno));
return OCXL_NO_DEV;
}
if (!(features.flags[0] & OCXL_IOCTL_FEATURES_FLAGS0_P9_WAIT)) {
errmsg(afu, OCXL_NO_DEV, "Power 9 wait is not available on this machine");
return OCXL_NO_DEV;
}
struct ocxl_ioctl_p9_wait wait_data;
rc = ioctl(my_afu->fd, OCXL_IOCTL_ENABLE_P9_WAIT, &wait_data);
if (rc) {
errmsg(afu, OCXL_NO_DEV, "Could not enable wait in kernel: %d %s",
errno, strerror(errno));
return OCXL_NO_DEV;
}
*thread_id = wait_data.thread_id;
return OCXL_OK;
}
/**
* @}
*/
libocxl-1.1.0/src/libocxl_internal.h 0000664 0000000 0000000 00000014526 13332436400 0017443 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef _LIBOCXL_INTERNAL_H
#define _LIBOCXL_INTERNAL_H
#define _ATFILE_SOURCE
#define _POSIX_C_SOURCE 200809L
#define _DEFAULT_SOURCE
#include
#include "libocxl.h"
#include
#include
/* LibOCXL is only tested with the following compilers:
* CLang 3.6.2, 3.7.1, 3.8.1, 3.9.1, 4.0.1, 5.0.2, 6.0.1
* GCC 4,5,6,7,8
*
* Use of other compilers may result in the MMIO functions emitting instructions
* that do not result in a 32/64 bit transfer across the OpenCAPI link.
*
* The above compilers have been manually verified to produce the following
* instructions in the mmio_*_native functions:
* lwz(x)/ld(x)
* stw(x)/std(x)
*/
#if defined(__clang__)
#if __clang_major__ < 3
#error LibOCXL has not been tested with this compiler, remove this error at your own peril
#elif __clang_major__ == 3 && __clang_minor__ < 6
#error LibOCXL has not been tested with this compiler, remove this error at your own peril
#endif // defined(__clang__)
#elif !defined(__GNUC__) || __GNUC__ < 4
#error LibOCXL has not been tested with this compiler, remove this error at your own peril
#endif
#define LIKELY(condition) __builtin_expect((condition), 1)
#define UNLIKELY(condition) __builtin_expect((condition), 0)
#define DEBUG(__dbg_format, __dbg_args...) \
do {\
trace_message("Debug", __FILE__, __LINE__, __FUNCTION__, __dbg_format, ## __dbg_args); \
} while (0)
#define TRACE(afu, __trc_format, __trc_args...) \
do {\
if (UNLIKELY(afu->tracing)) { \
trace_message("Trace", __FILE__, __LINE__, __FUNCTION__, __trc_format, ## __trc_args); \
} \
} while (0)
#define TRACE_OPEN(__trc_format, __trc_args...) \
do {\
if (UNLIKELY(tracing)) { \
trace_message("Trace", __FILE__, __LINE__, __FUNCTION__, __trc_format, ## __trc_args); \
} \
} while (0)
extern bool verbose_errors;
extern bool verbose_errors_all;
extern bool tracing;
extern bool tracing_all;
extern void (*error_handler)(ocxl_err error, const char *message);
extern const char *libocxl_info;
typedef struct ocxl_afu ocxl_afu;
void trace_message(const char *label, const char *file, int line, const char *function, const char *format, ...);
void errmsg(ocxl_afu *afu, ocxl_err error, const char *format, ...);
void ocxl_default_error_handler(ocxl_err error, const char *message);
void ocxl_default_afu_error_handler(ocxl_afu_h afu, ocxl_err error, const char *message);
ocxl_err grow_buffer(ocxl_afu *afu, void **buffer, uint16_t *count, size_t size, size_t initial_count);
ocxl_err global_mmio_open(ocxl_afu *afu);
extern const char *sys_path;
#define SYS_PATH_DEFAULT "/sys/class/ocxl"
#define SYS_PATH ((UNLIKELY(sys_path != NULL)) ? sys_path : SYS_PATH_DEFAULT)
extern const char *dev_path;
#define DEV_PATH_DEFAULT "/dev/ocxl"
#define DEVICE_PATH ((UNLIKELY(dev_path != NULL)) ? dev_path : DEV_PATH_DEFAULT)
#define INITIAL_IRQ_COUNT 64
#define INITIAL_MMIO_COUNT 4
/**
* @internal
* Represents an MMIO area from an AFU
*/
typedef struct ocxl_mmio_area {
char *start; /**< The first addressable byte of the area */
size_t length; /**< The size of the area in bytes */
ocxl_mmio_type type; /**< The type of the area */
ocxl_afu *afu; /**< The AFU this MMIO area belongs to */
} ocxl_mmio_area;
struct ocxl_irq;
typedef struct ocxl_irq ocxl_irq;
/**
* @internal
*
* The type of action to be taken upon return from the ocxl_read_afu_event() function
*/
typedef enum ocxl_event_action {
OCXL_EVENT_ACTION_SUCCESS, /**< The event read was successful and should be handled */
OCXL_EVENT_ACTION_FAIL, /**< The event read failed */
OCXL_EVENT_ACTION_NONE, /**< There was no event to read */
OCXL_EVENT_ACTION_IGNORE, /**< The event read was successful, but should be ignored */
} ocxl_event_action;
/**
* @internal
*
* Metadata for determining which source triggered an epoll fd
*/
typedef struct epoll_fd_source {
enum {
EPOLL_SOURCE_OCXL, /**< Source is the OpenCAPI infrastructure */
EPOLL_SOURCE_IRQ, /**< Source is an AFU generated IRQ */
} type;
union {
ocxl_irq *irq;
};
} epoll_fd_source;
/**
* @internal
*
* AFU IRQ information
*/
struct ocxl_irq {
struct ocxl_ioctl_irq_fd event; /**< The event descriptor */
uint16_t irq_number; /**< The 0 indexed IRQ number */
void *addr; /**< The mmapped address of the IRQ page */
void *info; /**< Additional info to pass to the user */
epoll_fd_source fd_info; /**< Epoll information for this IRQ */
};
/**
* @internal
*
* Represents an AFU
*/
struct ocxl_afu {
ocxl_identifier identifier; /**< The physical function, name and index of the AFU */
char *device_path;
char *sysfs_path;
uint8_t version_major;
uint8_t version_minor;
int fd; /**< A file descriptor for operating on the AFU */
epoll_fd_source fd_info; /**< Epoll information for the main AFU fd */
int epoll_fd; /**< A file descriptor for AFU IRQs wrapped with epoll */
struct epoll_event *epoll_events; /**< buffer for epoll return */
size_t epoll_event_count; /**< number of elements available in the epoll_events buffer */
int global_mmio_fd; /**< A file descriptor for accessing the AFU global MMIO area */
ocxl_mmio_area global_mmio;
ocxl_mmio_area per_pasid_mmio;
size_t page_size;
ocxl_irq *irqs;
uint16_t irq_count; /**< The number of valid IRQs */
uint16_t irq_max_count; /**< The maximum number of IRQs available */
ocxl_mmio_area *mmios;
uint16_t mmio_count; /**< The number of valid MMIO regions */
uint16_t mmio_max_count; /**< The maximum number of MMIO regions available */
uint32_t pasid;
bool verbose_errors;
void (*error_handler)(ocxl_afu_h afu, ocxl_err error, const char *message);
bool tracing;
pthread_mutex_t trace_mutex;
bool attached;
#ifdef _ARCH_PPC64
uint64_t ppc64_amr;
#endif
};
void irq_dealloc(ocxl_afu *afu, ocxl_irq *irq);
void libocxl_init();
#endif /* _LIBOCXL_INTERNAL_H */
libocxl-1.1.0/src/mmio.c 0000664 0000000 0000000 00000054571 13332436400 0015053 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libocxl_internal.h"
#include "sys/mman.h"
#include "errno.h"
#include
#include
#include
#include
#include
#include
/**
* @defgroup ocxl_mmio OpenCAPI MMIO Functions
*
* The MMIO functions map the global and per-PASID MMIO spaces of the AFU into
* the address space of the process, as well as moderating access to them.
*
* Only 32bit & 64bit accesses are supported.
*
* @{
*/
/**
* @internal
*
* Save a mapped MMIO region against an AFU.
*
* @param afu the AFU to operate on
* @param addr the address of the MMIO region
* @param size the size of the MMIO region
* @param type the type of the MMIO region
* @param[out] handle the MMIO region handle
*
* @retval OCXL_OK on success
* @retval OCXL_NO_MEM if there is insufficient memory
*/
static ocxl_err register_mmio(ocxl_afu *afu, void *addr, size_t size, ocxl_mmio_type type, ocxl_mmio_h *handle)
{
int available_mmio = -1;
// Look for an available MMIO region that has been unmapped
for (uint16_t mmio = 0; mmio < afu->mmio_count; mmio++) {
if (!afu->mmios[mmio].start) {
available_mmio = mmio;
break;
}
}
if (available_mmio == -1) {
if (afu->mmio_count == afu->mmio_max_count) {
ocxl_err rc = grow_buffer(afu, (void **)&afu->mmios, &afu->mmio_max_count, sizeof(ocxl_mmio_area), INITIAL_MMIO_COUNT);
if (rc != OCXL_OK) {
errmsg(afu, rc, "Could not grow MMIO buffer");
return rc;
}
}
available_mmio = afu->mmio_count++;
}
afu->mmios[available_mmio].start = addr;
afu->mmios[available_mmio].length = size;
afu->mmios[available_mmio].type = type;
afu->mmios[available_mmio].afu = afu;
*handle = &afu->mmios[available_mmio];
TRACE(afu, "Mapped %ld bytes of %s MMIO at %p",
size, type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID", addr);
return OCXL_OK;
}
/**
* Open the global MMIO descriptor on an AFU.
*
* @param afu the AFU
*
* @retval OCXL_NO_DEV if the MMIO descriptor could not be opened
*/
ocxl_err global_mmio_open(ocxl_afu *afu)
{
char path[PATH_MAX + 1];
int length = snprintf(path, sizeof(path), "%s/global_mmio_area", afu->sysfs_path);
if (length >= (int)sizeof(path)) {
ocxl_err rc = OCXL_NO_DEV;
errmsg(afu, rc, "global MMIO path truncated");
return rc;
}
int fd = open(path, O_RDWR | O_CLOEXEC);
if (fd < 0) {
ocxl_err rc = OCXL_NO_DEV;
errmsg(afu, rc, "Could not open global MMIO '%s': Error %d: %s", path, errno, strerror(errno));
return rc;
}
afu->global_mmio_fd = fd;
return OCXL_OK;
}
/**
* @internal
*
* map the Global MMIO area of an AFU to memory.
*
* Map the Global MMIO area of afu to the current process memory. The size and
* contents of this area are specific each AFU. The size can be discovered with
* ocxl_mmio_size().
*
* @pre the AFU has been opened
*
* @param afu the AFU to operate on
* @param size the size of the MMIO region to map (or 0 to map the full region)
* @param prot the protection parameters as per mmap/mprotect
* @param flags Additional flags to modify the map behavior (currently unused, must be 0)
* @param offset the offset of the MMIO region to map (or 0 to map the full region), should be a multiple of PAGE_SIZE
* @param[out] region the MMIO region handle
*
* @retval OCXL_OK on success
* @retval OCXL_NO_MEM if there is insufficient memory
* @retval OCXL_NO_DEV if the MMIO device could not be opened
* @retval OCXL_INVALID_ARGS if the flags are not valid
*/
static ocxl_err global_mmio_map(ocxl_afu *afu, size_t size, int prot, uint64_t flags, off_t offset,
ocxl_mmio_h *region) // static function extraction hack
{
if (afu->global_mmio.length == 0) {
ocxl_err rc = OCXL_NO_MEM;
errmsg(afu, rc, "Cannot map Global MMIO as there is 0 bytes allocated by the AFU");
return rc;
}
if (flags) {
ocxl_err rc = OCXL_INVALID_ARGS;
errmsg(afu, rc, "MMIO flags of 0x%llx is not supported by this version of libocxl", flags);
return rc;
}
void *addr = mmap(NULL, size, prot, MAP_SHARED, afu->global_mmio_fd, offset);
if (addr == MAP_FAILED) {
ocxl_err rc = OCXL_NO_MEM;
errmsg(afu, rc, "Could not map global MMIO, %d: %s", errno, strerror(errno));
return rc;
}
ocxl_mmio_h mmio_region;
ocxl_err rc = register_mmio(afu, addr, size, OCXL_GLOBAL_MMIO, &mmio_region);
if (rc != OCXL_OK) {
errmsg(afu, rc, "Could not register global MMIO region");
munmap(addr, size);
return rc;
}
*region = mmio_region;
return OCXL_OK;
}
/**
* @internal
*
* Map the per-PASID MMIO area of an AFU to memory.
*
* Map the per-PASID MMIO area of AFU to the current process memory. The size and
* contents of this area are specific each AFU. The size can be discovered with
* ocxl_mmio_size().
*
* @pre the AFU has been opened and attached
*
* @param afu the AFU to operate on
* @param size the size of the MMIO region to map (or 0 to map the full region)
* @param prot the protection parameters as per mmap/mprotect
* @param flags Additional flags to modify the map behavior (currently unused, must be 0)
* @param offset the offset of the MMIO region to map (or 0 to map the full region), should be a multiple of PAGE_SIZE
* @param[out] region the MMIO region handle
*
* @retval OCXL_OK on success
* @retval OCXL_NO_MEM if the map failed
* @retval OCXL_NO_CONTEXT if the AFU has not been opened/attached
* @retval OCXL_INVALID_ARGS if the flags are not valid
*/
static ocxl_err mmio_map(ocxl_afu *afu, size_t size, int prot, uint64_t flags, off_t offset, ocxl_mmio_h *region)
{
if (flags) {
ocxl_err rc = OCXL_INVALID_ARGS;
errmsg(afu, rc, "MMIO flags of 0x%llx is not supported by this version of libocxl", flags);
return rc;
}
if (afu->fd < 0) {
ocxl_err rc = OCXL_NO_CONTEXT;
errmsg(afu, rc, "Could not map per-PASID MMIO as the AFU has not been opened");
return rc;
}
if (!afu->attached) {
ocxl_err rc = OCXL_NO_CONTEXT;
errmsg(afu, rc, "Could not map per-PASID MMIO as the AFU has not been attached");
return rc;
}
void *addr = mmap(NULL, size, prot, MAP_SHARED, afu->fd, offset);
if (addr == MAP_FAILED) {
ocxl_err rc = OCXL_NO_MEM;
errmsg(afu, rc, "Could not map per-PASID MMIO: %d: %s", errno, strerror(errno));
return rc;
}
ocxl_mmio_h mmio_region;
ocxl_err rc = register_mmio(afu, addr, size, OCXL_PER_PASID_MMIO, &mmio_region);
if (rc != OCXL_OK) {
errmsg(afu, rc, "Could not register global MMIO region", afu->identifier.afu_name);
munmap(addr, size);
return rc;
}
*region = mmio_region;
return OCXL_OK;
}
/**
* Map an MMIO area of an AFU.
*
* Provides finer grain control of MMIO region mapping. Allows for protection parameters
* to be specified, as well as allowing partial mappings (with PAGE_SIZE granularity).
*
* @pre the AFU has been opened
*
* @param afu the AFU to operate on
* @param type the type of MMIO area to map
* @param size the size of the MMIO region to map (or 0 to map the full region)
* @param prot the protection parameters as per mmap/mprotect
* @param flags Additional flags to modify the map behavior (currently unused, must be 0)
* @param offset the offset of the MMIO region to map (or 0 to map the full region), should be a multiple of PAGE_SIZE
* @param[out] region the MMIO region handle
*
* @retval OCXL_OK on success
* @retval OCXL_NO_MEM if the map failed
* @retval OCXL_NO_CONTEXT if the AFU has not been opened
* @retval OCXL_INVALID_ARGS if the flags are not valid
*/
ocxl_err ocxl_mmio_map_advanced(ocxl_afu_h afu, ocxl_mmio_type type, size_t size, int prot, uint64_t flags,
off_t offset, ocxl_mmio_h *region)
{
ocxl_err rc = OCXL_INVALID_ARGS;
if (size == 0) {
switch (type) {
case OCXL_PER_PASID_MMIO:
size = afu->per_pasid_mmio.length;
break;
case OCXL_GLOBAL_MMIO:
size = afu->global_mmio.length;
break;
}
size -= offset;
}
switch (type) {
case OCXL_GLOBAL_MMIO:
if (offset + size > afu->global_mmio.length) {
rc = OCXL_NO_MEM;
errmsg(afu, rc, "Offset(%#x) + size(%#x) of global MMIO map request exceeds available size of %#x",
offset, size, afu->global_mmio.length);
return rc;
}
return global_mmio_map(afu, size, prot, flags, offset, region);
case OCXL_PER_PASID_MMIO:
if (offset + size > afu->per_pasid_mmio.length) {
rc = OCXL_NO_MEM;
errmsg(afu, rc, "Offset(%#x) + size(%#x) of per-pasid MMIO map request exceeds available size of %#x",
offset, size, afu->global_mmio.length);
return rc;
}
return mmio_map(afu, size, prot, flags, offset, region);
default:
errmsg(afu, rc, "Unknown MMIO type %d", type);
return rc;
}
}
/**
* Map an MMIO area of an AFU.
*
* Maps the entire global/per-PASID region of MMIO memory on the AFU with read/write access granted.
*
* @pre the AFU has been opened, and if a per-PASID region is to be mapped, the AFU has been attached
*
* @see ocxl_afu_attach()
*
* @param afu the AFU to operate on
* @param type the type of MMIO area to map
* @param region [out] the MMIO region handle
*
* @retval OCXL_OK on success
* @retval OCXL_NO_MEM if the map failed
* @retval OCXL_NO_CONTEXT if the AFU has not been opened
* @retval OCXL_INVALID_ARGS if the flags are not valid
*/
ocxl_err ocxl_mmio_map(ocxl_afu_h afu, ocxl_mmio_type type, ocxl_mmio_h *region)
{
return ocxl_mmio_map_advanced(afu, type, 0, PROT_READ | PROT_WRITE, 0, 0, region);
}
/**
* Unmap an MMIO region from an AFU.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param region the MMIO region to unmap
*/
void ocxl_mmio_unmap(ocxl_mmio_h region)
{
if (!region->start) {
return;
}
munmap(region->start, region->length);
region->start = NULL;
}
/**
* Get a file descriptor for an MMIO area of an AFU.
*
* Once obtained, the descriptor may be used to manually MMAP a section of the MMIO area.
*
* @see ocxl_mmio_size() to get the size of the MMIO areas
*
* @pre the AFU has been opened
*
* @param afu the AFU to operate on
* @param type the type of MMIO area to map
*
* @return the requested descriptor, or -1 if it is not available
*/
int ocxl_mmio_get_fd(ocxl_afu_h afu, ocxl_mmio_type type)
{
switch (type) {
case OCXL_GLOBAL_MMIO:
return afu->global_mmio_fd;
case OCXL_PER_PASID_MMIO:
return afu->fd;
default:
errmsg(afu, OCXL_INVALID_ARGS, "Unknown MMIO type %d", type);
return -1;
}
}
/**
* Get the size of an MMIO region for an AFU.
*
* @param afu the AFU to get the MMIO size of
* @param type the type of the MMIO region
*
* @return the size of the MMIO region in bytes
*/
size_t ocxl_mmio_size(ocxl_afu_h afu, ocxl_mmio_type type)
{
switch(type) {
case OCXL_GLOBAL_MMIO:
return afu->global_mmio.length;
case OCXL_PER_PASID_MMIO:
return afu->per_pasid_mmio.length;
default:
errmsg(afu, OCXL_INVALID_ARGS, "Invalid MMIO area requested '%d'", type);
return 0;
}
}
/**
* Get the address & size of a mapped MMIO region.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param region the MMIO region to get the details for
* @param address [out] The address of the MMIO region
* @param size [out] the size of the MMIO region in bytes
*
* @retval OCXL_OK if the details were retrieved
* @retval OCXL_INVALID_ARGS if the region is invalid
*/
ocxl_err ocxl_mmio_get_info(ocxl_mmio_h region, void **address, size_t *size)
{
if (!region->start) {
ocxl_err rc = OCXL_INVALID_ARGS;
errmsg(region->afu, rc, "MMIO region has already been unmapped");
return rc;
}
*address = region->start;
*size = region->length;
return OCXL_OK;
}
/**
* Validate an MMIO operation.
*
* @param region the MMIO region
* @param offset the offset within the MMIO area
* @param size the size of the operation
*
* @retval OCXL_OK if the operation can proceed
* @retval OCXL_INVALID_ARGS if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
inline static ocxl_err mmio_check(ocxl_mmio_h region, off_t offset, size_t size)
{
if (!region) {
ocxl_err rc = OCXL_INVALID_ARGS;
errmsg(NULL, rc, "MMIO region is invalid");
return rc;
}
if (!region->start) {
ocxl_err rc = OCXL_INVALID_ARGS;
errmsg(region->afu, rc, "MMIO region has already been unmapped");
return rc;
}
if (offset >= (off_t)(region->length - (size - 1))) {
ocxl_err rc = OCXL_OUT_OF_BOUNDS;
errmsg(region->afu, rc, "%s MMIO access of 0x%016lx exceeds limit of 0x%016lx",
region->type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID",
offset, region->length);
return rc;
}
return OCXL_OK;
}
/**
* Read a 32-bit value from an AFU's MMIO region.
*
* Read the 32-bit value at offset from the address of the mapped MMIO space,
* no endianness conversion will be performed.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the per-PASID MMIO area mapped
*
* @param region the MMIO area to operate on
* @param offset A byte address that is aligned on a word (4 byte) boundary. It
* must be lower than the MMIO size (-4 bytes) reported by ocxl_mmio_size()
* @param[out] out the value that was read
*
* @retval OCXL_OK if the value was read
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
inline static ocxl_err mmio_read32_native(ocxl_mmio_h region, off_t offset, uint32_t *out)
{
ocxl_err ret = mmio_check(region, offset, 4);
if (ret != OCXL_OK) {
return ret;
}
__sync_synchronize();
*out = *(volatile uint32_t *)(region->start + offset);
__sync_synchronize();
TRACE(region->afu, "%s MMIO Read32@0x%04lx=0x%08x",
region->type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID",
offset, *out);
return OCXL_OK;
}
/**
* Read a 64-bit value from an AFU's MMIO region.
*
* Read the 64-bit value at offset from the address of the mapped MMIO space,
* no endianness conversion will be performed.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the per-PASID MMIO area mapped
*
* @param region the MMIO area to operate on
* @param offset A byte address that is aligned on an 8 byte boundary. It
* must be lower than the MMIO size (-8 bytes) reported by ocxl_afu_get_mmio_size()
* @param[out] out the value that was read
*
* @retval OCXL_OK if the value was read
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
inline static ocxl_err mmio_read64_native(ocxl_mmio_h region, off_t offset, uint64_t *out)
{
ocxl_err ret = mmio_check(region, offset, 8);
if (ret != OCXL_OK) {
return ret;
}
__sync_synchronize();
*out = *(volatile uint64_t *)(region->start + offset);
__sync_synchronize();
TRACE(region->afu, "%s MMIO Read64@0x%04lx=0x%016lx",
region->type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID",
offset, *out);
return OCXL_OK;
}
/**
* Write a 32-bit value to an AFU's MMIO region.
*
* Write the 32-bit word at offset from the address of the mapped MMIO space,
* no endianness conversion will be performed.
*
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param afu the AFU to operate on
* @param region the MMIO area to operate on
* @param offset A byte address that is aligned on a 4 byte boundary. It
* must be lower than the MMIO size (-4 bytes) reported by ocxl_mmio_size()
* @param value the value to write
*
* @retval OCXL_OK if the value was written
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
inline static ocxl_err mmio_write32_native(ocxl_mmio_h region, off_t offset, uint32_t value)
{
ocxl_err ret = mmio_check(region, offset, 4);
if (ret != OCXL_OK) {
return ret;
}
TRACE(region->afu, "%s MMIO Write32@0x%04lx=0x%08x",
region->type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID",
offset, value);
volatile uint32_t *addr = (uint32_t *)(region->start + offset);
__sync_synchronize();
*addr = value;
__sync_synchronize();
return OCXL_OK;
}
/**
* Write a 64-bit value to the mapped AFU per-PASID MMIO space.
*
* Write the 64-bit value at offset from the address of the mapped MMIO space,
* no endianness conversion will be performed.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param region the MMIO area to operate on
* @param offset A byte address that is aligned on an 8 byte boundary. It
* must be lower than the MMIO size (-8 bytes) reported by ocxl_afu_get_mmio_size()
* @param value the value to write
*
* @retval OCXL_OK if the value was written
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
inline static ocxl_err mmio_write64_native(ocxl_mmio_h region, off_t offset, uint64_t value)
{
ocxl_err ret = mmio_check(region, offset, 8);
if (ret != OCXL_OK) {
return ret;
}
TRACE(region->afu, "%s MMIO Write64@0x%04lx=0x%016lx",
region->type == OCXL_GLOBAL_MMIO ? "Global" : "Per-PASID",
offset, value);
volatile uint64_t *addr = (uint64_t *)(region->start + offset);
__sync_synchronize();
*addr = value;
__sync_synchronize();
return OCXL_OK;
}
/**
* Read a 32-bit value from an AFU's MMIO region & convert endianness.
*
* Read the 32-bit value at offset from the address of the mapped MMIO space,
* and convert endianness as specified by the endian parameter.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
* @param mmio the MMIO area to operate on
* @param offset A byte address that is aligned on a word (4 byte) boundary. It
* must be lower than the MMIO size (-4 bytes) reported by ocxl_mmio_size()
* @param endian the endianness of the stored data (will be converted to native)
* @param[out] out the value that was read
*
* @retval OCXL_OK if the value was read
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
ocxl_err ocxl_mmio_read32(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint32_t *out)
{
uint32_t val;
ocxl_err ret = mmio_read32_native(mmio, offset, &val);
if (UNLIKELY(ret != OCXL_OK)) {
return ret;
}
switch (endian) {
case OCXL_MMIO_BIG_ENDIAN:
*out = be32toh(val);
break;
case OCXL_MMIO_LITTLE_ENDIAN:
*out = le32toh(val);
break;
default:
*out = val;
break;
}
return OCXL_OK;
}
/**
* Read a 64-bit value from an AFU's MMIO region & convert endianness.
*
* Read the 64-bit value at offset from the address of the mapped MMIO space,
* and convert endianness as specified by the endian parameter.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param mmio the MMIO area to operate on
* @param offset A byte address that is aligned on an 8 byte boundary. It
* must be lower than the MMIO size (-8 bytes) reported by ocxl_afu_get_mmio_size()
* @param endian the endianness of the stored data (will be converted to native)
* @param[out] out the value that was read
*
* @retval OCXL_OK if the value was read
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
ocxl_err ocxl_mmio_read64(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint64_t *out)
{
uint64_t val;
ocxl_err ret = mmio_read64_native(mmio, offset, &val);
if (UNLIKELY(ret != OCXL_OK)) {
return ret;
}
switch (endian) {
case OCXL_MMIO_BIG_ENDIAN:
*out = be64toh(val);
break;
case OCXL_MMIO_LITTLE_ENDIAN:
*out = le64toh(val);
break;
default:
*out = val;
break;
}
return OCXL_OK;
}
/**
* Convert endianness and write a 32-bit value to an AFU's MMIO region.
*
* Convert endianness and write the 32-bit word at offset from the address of the mapped MMIO space.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param mmio the MMIO area to operate on
* @param offset A byte address that is aligned on a 4 byte boundary. It
* must be lower than the MMIO size (-4 bytes) reported by ocxl_mmio_size()
*
* @param endian the endianness of the stored data (value will be converted to this before storing it)
* @param value the value to write
*
* @retval OCXL_OK if the value was written
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
ocxl_err ocxl_mmio_write32(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint32_t value)
{
switch (endian) {
case OCXL_MMIO_BIG_ENDIAN:
value = htobe32(value);
break;
case OCXL_MMIO_LITTLE_ENDIAN:
value = htole32(value);
break;
default:
break;
}
return mmio_write32_native(mmio, offset, value);
}
/**
* Convert endianness and write a 64-bit value to an AFU's MMIO region.
*
* Convert endianness and write the 32-bit word at offset from the address of the mapped MMIO space.
* Memory barriers are inserted before and after the MMIO operation.
*
* @pre the AFU has been opened, and the MMIO area mapped
*
* @param mmio the MMIO area to operate on
* @param offset A byte address that is aligned on an 8 byte boundary. It
* must be lower than the MMIO size (-8 bytes) reported by ocxl_mmio_size()
* @param endian the endianness of the stored data (value will be converted to this before storing it)
* @param value the value to write
*
* @retval OCXL_OK if the value was written
* @retval OCXL_NO_CONTEXT if the MMIO area is not mapped
* @retval OCXL_OUT_OF_BOUNDS if the offset exceeds the available area
*/
ocxl_err ocxl_mmio_write64(ocxl_mmio_h mmio, off_t offset, ocxl_endian endian, uint64_t value)
{
switch (endian) {
case OCXL_MMIO_BIG_ENDIAN:
value = htobe64(value);
break;
case OCXL_MMIO_LITTLE_ENDIAN:
value = htole64(value);
break;
default:
break;
}
return mmio_write64_native(mmio, offset, value);
}
/**
* @}
*/
libocxl-1.1.0/src/setup.c 0000664 0000000 0000000 00000007561 13332436400 0015247 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include "libocxl_internal.h"
#include
#include
/**
* @defgroup ocxl_messages OpenCAPI Messages
*
* These functions control messages from libocxl, such as error messages and tracing.
*
* @{
*/
#ifdef TEST_ENVIRONMENT
/**
* Set the directory used for the ocxl sysfs dir.
*
* Defaults to /sys/class/ocxl.
*
* @param path the new path to use for sysfs
*/
__attribute__ ((used)) static void ocxl_set_sys_path(const char *path)
{
sys_path = path;
}
/**
* Set the directory used for the ocxl dev dir.
*
* Defaults to /dev/ocxl.
*
* @param path the new path to use for sysfs
*/
__attribute__ ((used)) static void ocxl_set_dev_path(const char *path)
{
dev_path = path;
}
#endif // TEST_ENVIRONMENT
/**
* Enable messages from libocxl open calls.
*
* Error messages, if enabled, are emitted by default on STDERR. This behavior may be
* overridden by ocxl_afu_set_error_message_handler().
*
* Tracing, if enabled, is always emitted on STDERR. It assists a developer by showing
* detailed AFU information.
*
* @see ocxl_set_error_message_handler()
* @see ocxl_afu_enable_messages()
*
* @param sources a bitwise OR of the message sources to enable (OCXL_ERRORS, OCXL_TRACING)
*/
void ocxl_enable_messages(uint64_t sources)
{
verbose_errors = !!(sources & OCXL_ERRORS);
tracing = !!(sources & OCXL_TRACING);
}
/**
* Override the default handler for emitting error messages from open calls.
*
* The default error handler emits messages on STDERR, to override this behavior,
* pass a callback to this function.
*
* The callback is responsible for prefixing and line termination.
*
* Typical use cases would be redirecting error messages to the application's own
* logging/reporting mechanisms, and adding additional application-specific context
* to the error messages.
*
* @see ocxl_enable_messages()
* @see ocxl_err_to_string()
*
* @param handler the new error message handler
*/
void ocxl_set_error_message_handler(void (*handler)(ocxl_err error, const char *message))
{
error_handler = handler;
}
/**
* Convert an error value to a string.
*
* When implementing an error message handler, it may be useful to decode the provided
* ocxl_err to a human readable string, before logging the message.
*
* @see ocxl_set_error_message_handler()
* @see ocxl_afu_set_error_message_handler()
*
* @param err the error value
*
* @return a string representing a human readable version of the error value
*/
const char *ocxl_err_to_string(ocxl_err err)
{
switch (err) {
case OCXL_OK:
return "OK";
case OCXL_NO_MEM:
return "No memory";
case OCXL_NO_CONTEXT:
return "AFU context not available";
case OCXL_NO_IRQ:
return "AFU interrupt not available";
case OCXL_INTERNAL_ERROR:
return "Internal error";
case OCXL_ALREADY_DONE:
return "Already done";
case OCXL_OUT_OF_BOUNDS:
return "Out of bounds";
case OCXL_NO_MORE_CONTEXTS:
return "No more contexts";
case OCXL_INVALID_ARGS:
return "Invalid arguments";
default:
return "Unknown error";
}
}
/**
* Get version & compilation information about LibOCXL. This must be included with
* any bug report.
*
* The format and ordering of lines in this string may change.
*
* @return containing the version information
*/
const char *ocxl_info()
{
return libocxl_info;
}
/**
* @}
*/
libocxl-1.1.0/static-prototypes.pl 0000664 0000000 0000000 00000000227 13332436400 0017216 0 ustar 00root root 0000000 0000000 use English;
if (/static/) {
s/inline //;
s/static //;
s/__attribute__ \(\(used\)\) //;
s/^\s+/ /; s/,\n/,/;
s/\)/\);/;
s#//.*##;
print;
}
libocxl-1.1.0/symver.map 0000664 0000000 0000000 00000001641 13332436400 0015171 0 ustar 00root root 0000000 0000000 LIBOCXL_0 {
global:
ocxl_afu_enable_messages;
ocxl_afu_set_error_message_handler;
ocxl_default_afu_error_handler;
ocxl_default_error_handler;
ocxl_enable_messages;
ocxl_set_error_message_handler;
ocxl_err_to_string;
ocxl_info;
ocxl_afu_get_identifier;
ocxl_afu_get_device_path;
ocxl_afu_get_sysfs_path;
ocxl_afu_get_version;
ocxl_afu_get_pasid;
ocxl_afu_open_from_dev;
ocxl_afu_close;
ocxl_afu_open;
ocxl_afu_open_from_dev;
ocxl_afu_open_specific;
ocxl_afu_attach;
ocxl_irq_alloc;
ocxl_irq_get_handle;
ocxl_afu_get_event_fd;
ocxl_irq_get_fd;
ocxl_afu_event_check_versioned;
ocxl_afu_set_ppc64_amr;
ocxl_mmio_map;
ocxl_mmio_map_advanced;
ocxl_mmio_unmap;
ocxl_mmio_get_fd;
ocxl_mmio_size;
ocxl_mmio_get_info;
ocxl_mmio_read32;
ocxl_mmio_read64;
ocxl_mmio_write32;
ocxl_mmio_write64;
local:
*;
};
LIBOCXL_1_1 {
ocxl_afu_get_p9_thread_id;
};
libocxl-1.1.0/unittests/ 0000775 0000000 0000000 00000000000 13332436400 0015205 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/unittests/data/ 0000775 0000000 0000000 00000000000 13332436400 0016116 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/unittests/data/read_file_buf/ 0000775 0000000 0000000 00000000000 13332436400 0020664 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/unittests/data/read_file_buf/10 0000664 0000000 0000000 00000000003 13332436400 0021020 0 ustar 00root root 0000000 0000000 10
libocxl-1.1.0/unittests/data/read_file_buf/100 0000664 0000000 0000000 00000000004 13332436400 0021101 0 ustar 00root root 0000000 0000000 100
libocxl-1.1.0/unittests/data/read_file_buf/1000 0000664 0000000 0000000 00000000005 13332436400 0021162 0 ustar 00root root 0000000 0000000 1000
libocxl-1.1.0/unittests/data/read_file_buf/negative 0000664 0000000 0000000 00000000003 13332436400 0022402 0 ustar 00root root 0000000 0000000 -1
libocxl-1.1.0/unittests/data/read_file_buf/uint64_max 0000664 0000000 0000000 00000000025 13332436400 0022602 0 ustar 00root root 0000000 0000000 18446744073709551615
libocxl-1.1.0/unittests/data/read_file_uint/ 0000775 0000000 0000000 00000000000 13332436400 0021067 5 ustar 00root root 0000000 0000000 libocxl-1.1.0/unittests/data/read_file_uint/10 0000664 0000000 0000000 00000000003 13332436400 0021223 0 ustar 00root root 0000000 0000000 10
libocxl-1.1.0/unittests/data/read_file_uint/100 0000664 0000000 0000000 00000000004 13332436400 0021304 0 ustar 00root root 0000000 0000000 100
libocxl-1.1.0/unittests/data/read_file_uint/1000 0000664 0000000 0000000 00000000005 13332436400 0021365 0 ustar 00root root 0000000 0000000 1000
libocxl-1.1.0/unittests/data/read_file_uint/negative 0000664 0000000 0000000 00000000003 13332436400 0022605 0 ustar 00root root 0000000 0000000 -1
libocxl-1.1.0/unittests/data/read_file_uint/uint64_max 0000664 0000000 0000000 00000000025 13332436400 0023005 0 ustar 00root root 0000000 0000000 18446744073709551615
libocxl-1.1.0/unittests/unittests.c 0000664 0000000 0000000 00000065115 13332436400 0017423 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include "libocxl_internal.h"
#include "static.h"
#include
static const char *ocxl_sysfs_path = "/tmp/ocxl-test";
static const char *ocxl_dev_path = "/dev/ocxl-test";
#define MAX_TESTS 1024
#define TEST_NAME_LEN 32
#define SUITE_NAME_LEN 32
#define GLOBAL_MMIO_SIZE (32*1024*1024)
#define PER_PASID_MMIO_SIZE 16384
typedef enum state {
IN_PROGRESS,
SUCCESS,
SKIP,
FAIL
} state;
typedef struct test {
char suite[SUITE_NAME_LEN+1];
char name[TEST_NAME_LEN+1];
state state;
int count; /**< The number of checks performed */
} test;
test tests[MAX_TESTS];
int current_test = -1;
#define ASSERT(statement) do { \
tests[current_test].count++; \
if (!(statement)) { \
fprintf(stderr, "ASSERT: %s:%d: %s(): '%s' is false\n", __FILE__, __LINE__, __FUNCTION__, #statement); \
test_stop(FAIL); \
goto end; \
} \
} while(0)
#define SKIP(statement, msg) do { \
if ((statement)) { \
fprintf(stderr, "Skip: '%s' is true\n", #statement); \
test_stop(SKIP); \
goto end; \
} \
} while(0)
// virtocxl functions
pthread_t create_ocxl_device(const char *afu_name, size_t global_mmio_size, size_t per_pasid_mmio_size);
void stop_afu();
void term_afu();
#ifdef _ARCH_PPC64
void force_translation_fault(void *addr, uint64_t dsisr, uint64_t count);
#else
void force_translation_fault(void *addr, uint64_t dsisr);
#endif
bool afu_is_attached();
/**
* Start a test
* @param suite the name of the test suite
* @param name the name of the test
*/
static void test_start(const char *suite, const char *name) {
printf("Starting test %s:%s\n",
suite, name);
current_test++;
if (current_test == MAX_TESTS) {
fprintf(stderr, "Too many tests");
exit(1);
}
if (current_test && tests[current_test-1].state == IN_PROGRESS) {
fprintf(stderr, "Could not start '%s:%s', previous test '%s:%s' is still in progress",
suite, name, tests[current_test-1].suite, tests[current_test-1].name);
}
strncpy(tests[current_test].suite, suite, sizeof(tests->suite));
strncpy(tests[current_test].name, name, sizeof(tests->name));
tests[current_test].state = IN_PROGRESS;
tests[current_test].count = 0;
}
/**
* Complete the current test
* @param state the state of the test
*/
static void test_stop(state state) {
tests[current_test].state = state;
if (state == SUCCESS) {
printf("OK\n");
} else if (state == SKIP) {
printf("Skipped\n");
} else if (state == FAIL) {
printf("Failed\n");
}
}
/**
* Report the state of the tests
* @return true if we have failed tests
*/
static bool test_report() {
bool has_failed = false;
printf("Summary:\n");
int max_suite_name_len = 0;
int max_test_name_len = 0;
for (int test = 0; test <= current_test; test++) {
int len = strlen(tests[test].suite);
if (max_suite_name_len < len) {
max_suite_name_len = len;
}
len = strlen(tests[test].name);
if (max_test_name_len < len) {
max_test_name_len = len;
}
}
for (int test = 0; test <= current_test; test++) {
char *state;
switch (tests[test].state) {
case IN_PROGRESS:
state = "In Progress";
has_failed = true;
break;
case SUCCESS:
state = "OK";
break;
case SKIP:
state = "Skipped";
break;
case FAIL:
state = "Failed";
has_failed = true;
break;
default:
state = "Unknown";
has_failed = true;
break;
}
printf("\t%-*s\t%-*s\t%s\t%d checks\n",
max_suite_name_len, tests[test].suite,
max_test_name_len, tests[test].name, state, tests[test].count);
}
return has_failed;
}
/**
* Ensure the init call modifies the data structure
*/
static void test_afu_init() {
test_start("AFU", "init");
ocxl_afu afu1, afu2;
memset(&afu1, 0xff, sizeof(afu1));
memset(&afu2, 0xff, sizeof(afu2));
ASSERT(!memcmp(&afu1, &afu2, sizeof(afu1)));
afu_init(&afu1);
ASSERT(memcmp(&afu1, &afu2, sizeof(afu1)));
ocxl_afu_h afu = (ocxl_afu_h) &afu1;
ASSERT(ocxl_afu_get_device_path(afu) == NULL);
ASSERT(ocxl_afu_get_sysfs_path(afu) == NULL);
uint8_t major, minor;
ocxl_afu_get_version(afu, &major, &minor);
ASSERT(major == 0);
ASSERT(minor == 0);
ASSERT(ocxl_afu_get_event_fd(afu) == -1);
ASSERT(ocxl_mmio_size(afu, OCXL_GLOBAL_MMIO) == 0);
ASSERT(ocxl_mmio_size(afu, OCXL_PER_PASID_MMIO) == 0);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_GLOBAL_MMIO) == -1);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_PER_PASID_MMIO) == -1);
test_stop(SUCCESS);
end:
;
}
/**
* Check that the AFU can allocated
*/
static void test_ocxl_afu_alloc() {
test_start("AFU", "ocxl_afu_alloc");
ocxl_afu template;
afu_init(&template);
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == afu_alloc(&afu));
ASSERT(afu != 0);
ASSERT(ocxl_afu_get_device_path(afu) == NULL);
ASSERT(ocxl_afu_get_sysfs_path(afu) == NULL);
ASSERT(ocxl_afu_get_event_fd(afu) == -1);
ASSERT(ocxl_mmio_size(afu, OCXL_GLOBAL_MMIO) == 0);
ASSERT(ocxl_mmio_size(afu, OCXL_PER_PASID_MMIO) == 0);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_GLOBAL_MMIO) == -1);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_PER_PASID_MMIO) == -1);
test_stop(SUCCESS);
end:
ocxl_afu_close(afu);
}
/**
* Check device_matches
*/
static void test_device_matches() {
test_start("AFU", "device_matches");
DIR *dev_dir = opendir("/dev");
int dev_fd = dirfd(dev_dir);
struct stat urandom;
ASSERT(!fstatat(dev_fd, "urandom", &urandom, 0));
ASSERT(!device_matches(dev_fd, "zero", urandom.st_rdev));
ASSERT(device_matches(dev_fd, "urandom", urandom.st_rdev));
test_stop(SUCCESS);
end:
closedir(dev_dir);
}
pthread_t afu_thread = 0;
/**
* Create the virtual AFU
* @post afu_thread is set and must be joined
*/
static void create_afu() {
afu_thread = create_ocxl_device("IBM,Dummy", GLOBAL_MMIO_SIZE, PER_PASID_MMIO_SIZE);
if (!afu_thread) {
fprintf(stderr, "Could not create dummy AFU\n");
exit(1);
}
}
/**
* check populate_metadata()
*/
static void test_populate_metadata() {
test_start("AFU", "populate_metadata");
struct stat dev_stat;
ASSERT(!stat("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &dev_stat));
ocxl_afu afu;
afu_init(&afu);
ASSERT(populate_metadata(dev_stat.st_rdev, &afu));
ASSERT(!strcmp(afu.identifier.afu_name, "IBM,Dummy"));
ASSERT(afu.identifier.afu_index == 0);
ASSERT(!strcmp(afu.device_path, "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
ASSERT(!strcmp(afu.sysfs_path, "/tmp/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
test_stop(SUCCESS);
end:
;
}
/**
* Check get_afu_by_path
*/
static void test_get_afu_by_path() {
test_start("AFU", "get_afu_by_path");
ocxl_afu_h afu = OCXL_INVALID_AFU;
const char *symlink_path = "/tmp/ocxl-test-symlink";
ocxl_enable_messages(OCXL_NO_MESSAGES);
ASSERT(OCXL_NO_DEV == get_afu_by_path("/nonexistent", &afu));
ocxl_enable_messages(OCXL_ERRORS);
ASSERT(0 == afu);
afu = 0;
ASSERT(OCXL_OK == get_afu_by_path("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ASSERT(afu != 0);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
ocxl_afu_close(afu);
afu = 0;
ASSERT(0 == symlink("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", symlink_path));
ASSERT(OCXL_OK == get_afu_by_path(symlink_path, &afu));
ASSERT(afu != 0);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
test_stop(SUCCESS);
end:
ocxl_enable_messages(OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
unlink(symlink_path);
}
/**
* Check ocxl_afu_open
*/
static void test_afu_open() {
test_start("AFU", "afu_open");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == get_afu_by_path("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->fd == -1);
ASSERT(my_afu->epoll_fd == -1);
ASSERT(OCXL_OK == afu_open(afu));
ASSERT(my_afu->fd != -1);
ASSERT(my_afu->epoll_fd != -1);
ASSERT(ocxl_afu_get_event_fd(afu) != -1);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_GLOBAL_MMIO) != -1);
ASSERT(ocxl_mmio_get_fd(afu, OCXL_PER_PASID_MMIO) != -1);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_afu_open_specific
*/
static void test_ocxl_afu_open_specific() {
ocxl_afu_h afu = OCXL_INVALID_AFU - 1;
test_start("AFU", "ocxl_afu_open_specific");
ocxl_enable_messages(OCXL_NO_MESSAGES);
ASSERT(OCXL_NO_DEV == ocxl_afu_open_specific("nonexistent", NULL, -1, &afu));
ASSERT(afu == OCXL_INVALID_AFU);
ASSERT(OCXL_NO_DEV == ocxl_afu_open_specific("IBM,Dummy", "0001:00:00.2", -1, &afu));
ASSERT(OCXL_NO_DEV == ocxl_afu_open_specific("IBM,Dummy", "0001:00:00.1", 1, &afu));
ocxl_enable_messages(OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_open_specific("IBM,Dummy", "0001:00:00.1", 0, &afu));
ASSERT(afu != OCXL_INVALID_AFU);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
ocxl_afu_close(afu);
afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_specific("IBM,Dummy", "0001:00:00.1", -1, &afu));
ASSERT(afu != OCXL_INVALID_AFU);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->version_major == 5);
ASSERT(my_afu->version_minor == 10);
ASSERT(my_afu->global_mmio.length == 32*1024*1024);
ASSERT(my_afu->per_pasid_mmio.length == 16384);
ASSERT(my_afu->pasid == 1234);
test_stop(SUCCESS);
end:
ocxl_enable_messages(OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_afu_open_from_dev
*/
static void test_ocxl_afu_open_from_dev() {
test_start("AFU", "ocxl_afu_open_from_dev");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ocxl_enable_messages(OCXL_NO_MESSAGES);
ASSERT(OCXL_NO_DEV == ocxl_afu_open_from_dev("/nonexistent", &afu));
ocxl_enable_messages(OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->fd != -1);
ASSERT(my_afu->epoll_fd != -1);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
test_stop(SUCCESS);
end:
ocxl_enable_messages(OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check AFU getters
*/
static void test_afu_getters() {
test_start("AFU", "getters");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open("IBM,Dummy", &afu));
const ocxl_identifier *identifier = ocxl_afu_get_identifier(afu);
ASSERT(identifier->afu_index == 0);
ASSERT(!strcmp(identifier->afu_name, "IBM,Dummy"));
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
char expected_path[PATH_MAX];
snprintf(expected_path, sizeof(expected_path), "%s/IBM,Dummy.0001:00:00.1.0", ocxl_sysfs_path);
ASSERT(!strcmp(ocxl_afu_get_sysfs_path(afu), expected_path));
uint8_t major, minor;
ocxl_afu_get_version(afu, &major, &minor);
ASSERT(major == 5);
ASSERT(minor == 10);
ASSERT(ocxl_afu_get_event_fd(afu) >= 0);
ASSERT(ocxl_mmio_size(afu, OCXL_GLOBAL_MMIO) == 32*1024*1024);
ASSERT(ocxl_mmio_size(afu, OCXL_PER_PASID_MMIO) == 16384);
ASSERT(ocxl_afu_get_pasid(afu) == 1234);
ASSERT(ocxl_afu_get_event_fd(afu) != -1);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_afu_open
*/
static void test_ocxl_afu_open() {
test_start("AFU", "ocxl_afu_open");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ocxl_enable_messages(OCXL_NO_MESSAGES);
ASSERT(OCXL_NO_DEV == ocxl_afu_open("nonexistent", &afu));
ocxl_enable_messages(OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_open("IBM,Dummy", &afu));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->fd != -1);
ASSERT(my_afu->epoll_fd != -1);
ASSERT(!strcmp(ocxl_afu_get_device_path(afu), "/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0"));
test_stop(SUCCESS);
end:
ocxl_enable_messages(OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_afu_attach
*/
static void test_ocxl_afu_attach() {
test_start("AFU", "ocxl_afu_attach");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(!afu_is_attached());
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_attach(afu, OCXL_ATTACH_FLAGS_NONE));
ASSERT(afu_is_attached());
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_afu_close
*/
static void test_ocxl_afu_close() {
test_start("AFU", "ocxl_afu_close");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_close(afu));
ASSERT(afu != 0);
/* We deliberately dereference the freed ocxl_afu here to ensure the contents have
* been cleared appropriately. The data should not have been reallocated and overwritten yet
*/
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(0 == my_afu->irq_count);
ASSERT(0 == my_afu->irq_max_count);
ASSERT(0 == my_afu->epoll_event_count);
ASSERT(-1 == my_afu->fd);
ASSERT(-1 == my_afu->epoll_fd);
ASSERT(NULL == my_afu->device_path);
ASSERT(NULL == my_afu->sysfs_path);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check ocxl_mmio_map/unmap
*/
static void test_ocxl_mmio_map() {
test_start("MMIO", "ocxl_mmio_map/unmap");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->global_mmio_fd != -1);
ASSERT(my_afu->global_mmio.start == NULL);
ASSERT(my_afu->global_mmio.length == GLOBAL_MMIO_SIZE);
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
ASSERT(my_afu->global_mmio_fd != -1);
void *addr;
size_t size;
ASSERT(OCXL_OK == ocxl_mmio_get_info(global_mmio, &addr, &size));
ASSERT(addr != NULL);
ASSERT(size == GLOBAL_MMIO_SIZE);
ocxl_mmio_unmap(global_mmio);
ASSERT(my_afu->global_mmio_fd != -1); // FD left open for further use
ASSERT(my_afu->mmios[0].start == NULL);
ASSERT(OCXL_OK == ocxl_afu_close(afu));
ASSERT(my_afu->global_mmio_fd == -1);
ASSERT(my_afu->global_mmio.start == NULL);
ASSERT(my_afu->global_mmio.length == GLOBAL_MMIO_SIZE);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check mmio_check
*/
static void test_mmio_check() {
test_start("MMIO", "mmio_check");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ASSERT(my_afu->global_mmio_fd != -1);
ASSERT(my_afu->global_mmio.start == NULL);
ASSERT(my_afu->global_mmio.length == GLOBAL_MMIO_SIZE);
ocxl_afu_enable_messages(afu, OCXL_NO_MESSAGES);
ASSERT(OCXL_INVALID_ARGS == mmio_check(0, 0, 4));
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
ASSERT(OCXL_OUT_OF_BOUNDS == mmio_check(global_mmio, GLOBAL_MMIO_SIZE + 8, 4));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ASSERT(OCXL_OK == mmio_check(global_mmio, 0, 4));
test_stop(SUCCESS);
end:
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check read32/write32_native
*/
static void test_ocxl_mmio_read32_native() {
test_start("MMIO", "ocxl_mmio_read32/write32_native");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
ASSERT(OCXL_OK == mmio_write32_native(global_mmio, offset, offset));
}
bool good = true;
for (uint32_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
uint32_t val;
ASSERT(OCXL_OK == mmio_read32_native(global_mmio, offset, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
ocxl_mmio_unmap(global_mmio);
test_stop(SUCCESS);
end:
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check read64/write64_native
*/
static void test_ocxl_mmio_read64_native() {
test_start("MMIO", "ocxl_mmio_read64/write64_native");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
ASSERT(OCXL_OK == mmio_write64_native(global_mmio, offset, offset));
}
bool good = true;
for (uint64_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
uint64_t val;
ASSERT(OCXL_OK == mmio_read64_native(global_mmio, offset, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
ocxl_mmio_unmap(global_mmio);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check read32/write32
*/
static void test_ocxl_mmio_read32() {
test_start("MMIO", "ocxl_mmio_read32/write32");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
ocxl_mmio_area *mmio = (ocxl_mmio_area *)global_mmio;
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
ASSERT(OCXL_OK == ocxl_mmio_write32(global_mmio, offset, OCXL_MMIO_BIG_ENDIAN, offset));
}
bool good = true;
for (uint32_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
uint32_t val;
ASSERT(OCXL_OK == ocxl_mmio_read32(global_mmio, offset, OCXL_MMIO_BIG_ENDIAN, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
uint32_t big = *(uint32_t *)(mmio->start + 4);
ASSERT(4 == be32toh(big));
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
ASSERT(OCXL_OK == ocxl_mmio_write32(global_mmio, offset, OCXL_MMIO_LITTLE_ENDIAN, offset));
}
for (uint32_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 4) {
uint32_t val;
ASSERT(OCXL_OK == ocxl_mmio_read32(global_mmio, offset, OCXL_MMIO_LITTLE_ENDIAN, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
uint32_t little = *(uint32_t *)(mmio->start + 4);
ASSERT(4 == le32toh(little));
ASSERT(big != little);
ocxl_mmio_unmap(global_mmio);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check read64/write64
*/
static void test_ocxl_mmio_read64() {
test_start("MMIO", "ocxl_mmio_read64/write64");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ocxl_mmio_h global_mmio;
ASSERT(OCXL_OK == ocxl_mmio_map(afu, OCXL_GLOBAL_MMIO, &global_mmio));
ocxl_mmio_area *mmio = (ocxl_mmio_area *)global_mmio;
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
ASSERT(OCXL_OK == ocxl_mmio_write64(global_mmio, offset, OCXL_MMIO_BIG_ENDIAN, offset));
}
bool good = true;
for (uint64_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
uint64_t val;
ASSERT(OCXL_OK == ocxl_mmio_read64(global_mmio, offset, OCXL_MMIO_BIG_ENDIAN, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
uint64_t big = *(uint64_t *)(mmio->start + 8);
ASSERT(8 == be64toh(big));
for (int offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
ASSERT(OCXL_OK == ocxl_mmio_write64(global_mmio, offset, OCXL_MMIO_LITTLE_ENDIAN, offset));
}
for (uint64_t offset = 0; offset < GLOBAL_MMIO_SIZE; offset += 8) {
uint64_t val;
ASSERT(OCXL_OK == ocxl_mmio_read64(global_mmio, offset, OCXL_MMIO_LITTLE_ENDIAN, &val));
if (val != offset) {
good = false;
break;
}
}
ASSERT(good);
uint64_t little = *(uint64_t *)(mmio->start + 8);
ASSERT(8 == le64toh(little));
ASSERT(big != little);
ocxl_mmio_unmap(global_mmio);
test_stop(SUCCESS);
end:
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
if (afu) {
ocxl_afu_close(afu);
}
}
/**
* Check read_afu_event
*/
static void test_read_afu_event() {
test_start("IRQ", "read_afu_event");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
ASSERT(OCXL_OK == ocxl_afu_attach(afu, OCXL_ATTACH_FLAGS_NONE));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ocxl_event event;
int last = 0;
ASSERT(OCXL_EVENT_ACTION_NONE == read_afu_event(my_afu, 0, &event, &last));
ASSERT(last);
#ifdef _ARCH_PPC64
force_translation_fault((void *)0xfeeddeadbeeff00d, 0x123456789abcdef0, 16);
#else
force_translation_fault((void *)0xfeeddeadbeeff00d, 16);
#endif
last = 0;
ASSERT(OCXL_EVENT_ACTION_SUCCESS == read_afu_event(my_afu, 0, &event, &last));
ASSERT(last);
ASSERT(event.type == OCXL_EVENT_TRANSLATION_FAULT);
ASSERT(event.translation_fault.addr == (void *)0xfeeddeadbeeff00d);
#ifdef _ARCH_PPC64
ASSERT(event.translation_fault.dsisr == 0x123456789abcdef0);
#endif
ASSERT(event.translation_fault.count == 16);
#ifdef _ARCH_PPC64
force_translation_fault((void *)0xfeeddeadbeeff00d, 0x123456789abcdef0, 16);
#else
force_translation_fault((void *)0xfeeddeadbeeff00d, 16);
#endif
last = 0;
ASSERT(OCXL_EVENT_ACTION_SUCCESS == read_afu_event(my_afu, 0, &event, &last));
ASSERT(last);
ASSERT(event.type == OCXL_EVENT_TRANSLATION_FAULT);
ASSERT(event.translation_fault.addr == (void *)0xfeeddeadbeeff00d);
#ifdef _ARCH_PPC64
ASSERT(event.translation_fault.dsisr == 0x123456789abcdef0);
#endif
ASSERT(event.translation_fault.count == 16);
last = 0;
ASSERT(OCXL_EVENT_ACTION_NONE == read_afu_event(my_afu, 0, &event, &last));
ASSERT(last);
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
#ifdef __UNUSED
/**
* Check ocxl_afu_event_check_versioned (with kernel events)
*/
static void test_ocxl_afu_event_check_versioned() {
test_start("IRQ", "ocxl_afu_event_check_versioned (kernel)");
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ASSERT(OCXL_OK == ocxl_afu_attach(afu, afu_attach));
#define EVENT_COUNT 5
ocxl_event events[EVENT_COUNT];
ASSERT(0 == ocxl_afu_event_check_versioned(afu, 10, events, EVENT_COUNT, 0));
#ifdef _ARCH_PPC64
force_translation_fault((void *)0xfeeddeadbeeff00d, 0x123456789abcdef0, 16);
#else
force_translation_fault((void *)0xfeeddeadbeeff00d, 16);
#endif
ASSERT(1 == ocxl_afu_event_check_versioned(afu, 10, events, EVENT_COUNT, 0));
ASSERT(events[0].type == OCXL_EVENT_TRANSLATION_FAULT);
ASSERT(events[0].translation_fault.addr == (void *)0xfeeddeadbeeff00d);
#ifdef _ARCH_PPC64
ASSERT(events[0].translation_fault.dsisr == 0x123456789abcdef0);
#endif
ASSERT(events[0].translation_fault.count == 16);
ASSERT(0 == ocxl_afu_event_check_versioned(afu, 0, events, EVENT_COUNT, 0));
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
#endif
#define MAX_MESSAGE_LENGTH 255 // From internal.c
char err_buf[MAX_MESSAGE_LENGTH];
static void copy_to_err_buf(ocxl_err error, const char *message) {
snprintf(err_buf, sizeof(err_buf), "%s: %s", ocxl_err_to_string(error), message);
}
/**
* Test the error reporting callback (open calls)
*/
static void test_ocxl_set_error_message_handler() {
test_start("ERR", "ocxl_set_error_message_handler");
memset(err_buf, '\0', sizeof(err_buf));
ocxl_set_error_message_handler(copy_to_err_buf);
ocxl_enable_messages(OCXL_ERRORS);
const char *message = "error message test";
errmsg(NULL, OCXL_INTERNAL_ERROR, "%s", message);
ASSERT(!strcmp("Internal error: error message test", err_buf));
test_stop(SUCCESS);
end:
ocxl_set_error_message_handler(ocxl_default_error_handler);
}
static void copy_to_err_buf_afu(ocxl_afu_h afu, ocxl_err error, const char *message) {
const ocxl_identifier *id = ocxl_afu_get_identifier(afu);
uint8_t major, minor;
ocxl_afu_get_version(afu, &major, &minor);
snprintf(err_buf, sizeof(err_buf), "%s(%d,%d): %s: %s",
id->afu_name, major, minor, ocxl_err_to_string(error), message);
}
/**
* Test the error reporting callback (AFU calls)
*/
static void test_ocxl_set_afu_error_message_handler() {
test_start("ERR", "ocxl_set_afu_error_message_handler");
memset(err_buf, '\0', sizeof(err_buf));
ocxl_afu_h afu = OCXL_INVALID_AFU;
ASSERT(OCXL_OK == ocxl_afu_open_from_dev("/dev/ocxl-test/IBM,Dummy.0001:00:00.1.0", &afu));
ocxl_afu *my_afu = (ocxl_afu *)afu;
ocxl_afu_set_error_message_handler(afu, copy_to_err_buf_afu);
ocxl_afu_enable_messages(afu, OCXL_ERRORS);
const char *message = "error message test";
errmsg(my_afu, OCXL_INTERNAL_ERROR, "%s", message);
ASSERT(!strcmp("IBM,Dummy(5,10): Internal error: error message test", err_buf));
test_stop(SUCCESS);
end:
if (afu) {
ocxl_afu_close(afu);
}
}
static void exit_handler() {
void *ret;
if (afu_thread) {
stop_afu();
pthread_kill(afu_thread, SIGTERM);
pthread_join(afu_thread, &ret);
term_afu();
}
}
int main(__attribute__((unused)) int args, __attribute__((unused)) const char **argv) {
struct sigaction sa;
sa.sa_handler = exit_handler;
sigemptyset(&(sa.sa_mask));
sa.sa_flags = 0;
(void)sigaction(SIGINT, &sa, NULL);
ocxl_set_sys_path(ocxl_sysfs_path);
ocxl_set_dev_path(ocxl_dev_path);
ocxl_enable_messages(OCXL_ERRORS);
struct stat sysfs_stat;
if (stat(ocxl_sysfs_path, &sysfs_stat)) {
if (mkdir(ocxl_sysfs_path, 0775)) {
fprintf(stderr, "Could not mkdir '%s': %d: %s\n",
ocxl_sysfs_path, errno, strerror(errno));
}
}
test_afu_init();
test_ocxl_afu_alloc();
test_device_matches();
create_afu();
sleep(1);
test_populate_metadata();
test_afu_getters();
test_get_afu_by_path();
test_afu_open();
test_ocxl_afu_open_specific();
test_ocxl_afu_open_from_dev();
test_ocxl_afu_open();
test_ocxl_afu_attach();
test_ocxl_afu_close();
test_ocxl_set_error_message_handler();
test_ocxl_set_afu_error_message_handler();
test_ocxl_mmio_map();
test_mmio_check();
test_ocxl_mmio_read32_native();
test_ocxl_mmio_read64_native();
test_ocxl_mmio_read32();
test_ocxl_mmio_read64();
test_read_afu_event();
// Disabled as we need epoll support in CUSE to test this
// test_ocxl_afu_event_check_versioned();
exit_handler();
if (test_report()) {
return 1;
}
return 0;
}
libocxl-1.1.0/unittests/virtocxl.c 0000664 0000000 0000000 00000016471 13332436400 0017234 0 ustar 00root root 0000000 0000000 /*
* Copyright 2017 International Business Machines
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#include
#include
#include
#include "libocxl_internal.h"
#include
#include
#include
#include
#include
#include
#include
#include
#include
typedef struct ocxl_kernel_event_header ocxl_kernel_event_header;
typedef struct ocxl_kernel_event_xsl_fault_error ocxl_kernel_event_xsl_fault_error;
#define KERNEL_EVENT_SIZE (sizeof(ocxl_kernel_event_header) + sizeof(ocxl_kernel_event_xsl_fault_error))
ocxl_kernel_event_xsl_fault_error translation_fault = { .addr = 0 };
bool afu_attached = false;
const char *sysfs_path = NULL;
static uint8_t version_major = 5;
static uint8_t version_minor = 10;
static size_t _global_mmio_size = 0;
static size_t _pp_mmio_size = 0;
static void afu_open(fuse_req_t req, struct fuse_file_info *fi)
{
afu_attached = false;
fuse_reply_open(req, fi);
}
static void afu_read(fuse_req_t req, size_t size, off_t off, __attribute__((unused)) struct fuse_file_info *fi)
{
char buf[KERNEL_EVENT_SIZE];
ocxl_kernel_event_header header = {
.type = OCXL_AFU_EVENT_XSL_FAULT_ERROR,
.flags = OCXL_KERNEL_EVENT_FLAG_LAST,
};
if (0 != off) {
fuse_reply_err(req, EINVAL);
return;
}
if (translation_fault.addr == 0) {
fuse_reply_err(req, EAGAIN);
return;
}
if (size < KERNEL_EVENT_SIZE) {
fuse_reply_buf(req, buf, 0);
return;
}
memcpy(buf, &header, sizeof(header));
memcpy(buf + sizeof(header), &translation_fault, sizeof(translation_fault));
fuse_reply_buf(req, buf, size);
translation_fault.addr = 0;
}
static void afu_ioctl(fuse_req_t req, int cmd, __attribute__((unused)) void *arg,
__attribute__((unused)) struct fuse_file_info *fi, __attribute__((unused)) unsigned flags,
__attribute__((unused)) const void *in_buf, __attribute__((unused)) size_t in_bufsz,
__attribute__((unused)) size_t out_bufsz)
{
struct ocxl_ioctl_metadata ret;
switch (cmd) {
case OCXL_IOCTL_ATTACH:
afu_attached = true;
fuse_reply_ioctl(req, 0, NULL, 0);
break;
case OCXL_IOCTL_GET_METADATA:
memset(&ret, 0, sizeof(ret));
ret.version = 1;
ret.afu_version_major = version_major;
ret.afu_version_minor = version_minor;
ret.pasid = 1234;
ret.pp_mmio_size = _pp_mmio_size;
ret.global_mmio_size = _global_mmio_size;
fuse_reply_ioctl(req, 0, &ret, sizeof(ret));
break;
default:
fuse_reply_err(req, EINVAL);
}
}
static void afu_poll (fuse_req_t req, __attribute__((unused)) struct fuse_file_info *fi,
__attribute__((unused)) struct fuse_pollhandle *ph)
{
if (translation_fault.addr != 0) {
fuse_reply_poll(req, POLLIN | POLLRDNORM);
} else if (!afu_attached) {
fuse_reply_poll(req, POLLERR);
}
fuse_reply_poll(req, 0);
}
#define DEVICE_NAME_MAX 64
#define BUF_SIZE 1024
typedef struct afu_thread_info {
char device_name[DEVICE_NAME_MAX];
struct cuse_info cuse;
struct cuse_lowlevel_ops afu_ops;
} afu_thread_info;
afu_thread_info afu_info;
struct fuse_session *afu_session = NULL;
static void *start_afu_thread(void *arg) {
afu_thread_info *info = (afu_thread_info *)arg;
char dev_name[PATH_MAX+9] = "DEVNAME=";
const char *dev_info_argv[] = { dev_name };
strncat(dev_name, info->device_name, sizeof(dev_name) - 9);
memset(&info->cuse, 0, sizeof(info->cuse));
info->cuse.dev_major = 0;
info->cuse.dev_minor = 0;
info->cuse.dev_info_argc = 1;
info->cuse.dev_info_argv = dev_info_argv;
info->cuse.flags = 0;
char *argv[] = {
"testobj/unittests",
"-f",
};
struct fuse_args args = FUSE_ARGS_INIT(2, argv);
afu_session = cuse_lowlevel_setup(args.argc, args.argv, &info->cuse, &info->afu_ops, NULL, NULL);
(void)fuse_session_loop(afu_session);
return NULL;
}
void stop_afu() {
fuse_session_exit(afu_session);
}
void term_afu() {
if (afu_session) {
fuse_session_destroy(afu_session);
afu_session = NULL;
}
}
/**
* Is the current AFU instance attached
* @return true if the AFU is attached
*/
bool afu_is_attached() {
return afu_attached;
}
/**
* Create a new virtual OCXL device.
*
* @param afu_name the name of the AFU
* @param global_mmio_size the size of the global MMIO area
* @param per_pasid_mmio_size the size of the per-PASID MMIO area
*
* @return the thread for the device, or 0 on error
*/
pthread_t create_ocxl_device(const char *afu_name, size_t global_mmio_size, size_t per_pasid_mmio_size) {
char sysfs_base[PATH_MAX];
char tmp[PATH_MAX];
char buf[BUF_SIZE];
_global_mmio_size = global_mmio_size;
_pp_mmio_size = per_pasid_mmio_size;
snprintf(afu_info.device_name, sizeof(afu_info.device_name), "ocxl-test/%s.0001:00:00.1.0", afu_name);
snprintf(sysfs_base, sizeof(sysfs_base), "%s/%s.0001:00:00.1.0", SYS_PATH, afu_name);
struct stat sysfs_stat;
if (stat(sysfs_base, &sysfs_stat)) {
if (mkdir(sysfs_base, 0775)) {
fprintf(stderr, "Could not mkdir '%s': %d: %s\n",
sysfs_base, errno, strerror(errno));
}
}
// Create global MMIO area file
snprintf(tmp, sizeof(tmp), "%s/global_mmio_area", sysfs_base);
int fd = creat(tmp, S_IWUSR | S_IRUSR | S_IRGRP | S_IROTH);
if (fd < 0) {
fprintf(stderr, "Could not create global_mmio_area file '%s': %d: %s\n",
tmp, errno, strerror(errno));
return 0;
}
memset(buf, 0, sizeof(buf));
for (size_t offset = 0; offset < global_mmio_size; offset += sizeof(buf)) {
int written = write(fd, buf, sizeof(buf));
if (written < 0) {
fprintf(stderr, "Could not write global_mmio_area file '%s': %d: %s\n",
tmp, errno, strerror(errno));
return 0;
}
}
close(fd);
memset(&afu_info.afu_ops, 0, sizeof(afu_info.afu_ops));
afu_info.afu_ops.open = afu_open;
afu_info.afu_ops.read = afu_read;
afu_info.afu_ops.ioctl = afu_ioctl;
afu_info.afu_ops.poll = afu_poll;
pthread_t afu_thread = 1;
if (pthread_create(&afu_thread, NULL, start_afu_thread, &afu_info)) {
fprintf(stderr, "Could not create AFU thread\n");
return 0;
}
return afu_thread;
}
#ifdef _ARCH_PPC64
/**
* Force a translation fault, this should cause afu_poll() to register an event, and afu_read() to return the event.
*
* @param addr the address of the fault
* @param dsisr the value of the PPC64 specific DSISR register
* @param count the number of times the translation fault has triggered an error
*/
void force_translation_fault(void *addr, uint64_t dsisr, uint64_t count) {
translation_fault.addr = (uint64_t)addr;
translation_fault.dsisr = dsisr;
translation_fault.count = count;
}
#else
/**
* Force a translation fault, this should cause afu_poll() to register an event, and afu_read() to return the event.
*
* @param addr the address of the fault
* @param count the number of times the translation fault has triggered an error
*/
void force_translation_fault(void *addr, uint64_t count) {
translation_fault.addr = (__u64)addr;
translation_fault.count = count;
}
#endif
libocxl-1.1.0/version.pl 0000775 0000000 0000000 00000001425 13332436400 0015172 0 ustar 00root root 0000000 0000000 #!/usr/bin/env perl
use English;
use strict;
use warnings;
my $compilerText = `$ENV{CC} --version`;
my @compilerLines = split /\n/, $compilerText;
chomp @compilerLines;
my $git = `which git`;
my $gitHash = '';
if ($git && -d '.git') {
chomp $git;
my $hash = `$git rev-parse HEAD`;
chomp $hash;
my $dirty = '';
my @changed = `git diff-index --name-only HEAD`;
if (@changed) {
$dirty = '-dirty';
}
$gitHash = "\"Git hash: $hash$dirty\\n\"";
}
my $platform = `uname -srvmpio`;
chomp $platform;
print <<"EOF";
const char *libocxl_info =
"LibOCXL Version: $ENV{VERSION_MAJOR}.$ENV{VERSION_MINOR}.$ENV{VERSION_PATCH}\\n"
"CC: $ENV{CC}\\n"
"Compiler Version: $compilerLines[0]\\n"
"CFLAGS: $ENV{CFLAGS}\\n"
$gitHash
"Build platform: $platform\\n";
EOF