Index: projects/make-check-sandbox/contrib/libxo/Makefile.am =================================================================== --- projects/make-check-sandbox/contrib/libxo/Makefile.am (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/Makefile.am (revision 322022) @@ -1,124 +1,143 @@ # # $Id$ # # Copyright 2014, Juniper Networks, Inc. # All rights reserved. # This SOFTWARE is licensed under the LICENSE provided in the # ../Copyright file. By downloading, installing, copying, or otherwise # using the SOFTWARE, you agree to be bound by the terms of that # LICENSE. ACLOCAL_AMFLAGS = -I m4 SUBDIRS = libxo xo xopo xolint xohtml tests doc encoder bin_SCRIPTS=libxo-config dist_doc_DATA = Copyright EXTRA_DIST = \ libxo-config.in \ warnings.mk \ README.md \ INSTALL.md \ packaging/libxo.spec .PHONY: test tests test tests: @(cd tests ; ${MAKE} test) errors: @(cd tests/errors ; ${MAKE} test) docs: @(cd doc ; ${MAKE} docs) DIST_FILES_DIR = ~/Dropbox/dist-files/ GH_PAGES_DIR = gh-pages/ GH_PAGES_DIR_VER = gh-pages/${PACKAGE_VERSION} PACKAGE_FILE = ${PACKAGE_TARNAME}-${PACKAGE_VERSION}.tar.gz -upload: dist upload-docs +XOHTML_FILES = \ + ${top_srcdir}/xohtml/xohtml.css \ + ${top_srcdir}/xohtml/xohtml.js \ + ${top_srcdir}/xohtml/external/jquery.js \ + ${top_srcdir}/xohtml/external/jquery.qtip.css \ + ${top_srcdir}/xohtml/external/jquery.qtip.js + +upload: dist upload-docs upload-xohtml-files @echo "Remember to run:" @echo " gt tag ${PACKAGE_VERSION}" upload-docs: docs @echo "Uploading libxo-manual.html ... " @-[ -d ${GH_PAGES_DIR} ] \ && echo "Updating manual on gh-pages ..." \ && mkdir -p ${GH_PAGES_DIR_VER} \ && cp doc/libxo-manual.html ${GH_PAGES_DIR} \ && cp doc/libxo-manual.html ${GH_PAGES_DIR_VER} \ && (cd ${GH_PAGES_DIR} \ && git add ${PACKAGE_VERSION} \ && git add libxo-manual.html \ && git commit -m 'new docs' \ libxo-manual.html ${PACKAGE_VERSION} \ + && git push origin gh-pages ) ; true + +upload-xohtml-files: + @echo "Uploading xohtml files ... " + @-[ -d ${GH_PAGES_DIR} ] \ + && echo "Updating xohtml files on gh-pages ..." \ + && mkdir -p ${GH_PAGES_DIR_VER}/xohtml \ + && cp ${XOHTML_FILES} ${GH_PAGES_DIR_VER}/xohtml \ + && (cd ${GH_PAGES_DIR} \ + && git add ${PACKAGE_VERSION}/xohtml \ + && git commit -m 'new xohtml files' \ + ${PACKAGE_VERSION}/xohtml \ && git push origin gh-pages ) ; true pkgconfigdir=$(libdir)/pkgconfig pkgconfig_DATA = packaging/${PACKAGE_NAME}.pc get-wiki: git clone https://github.com/Juniper/${PACKAGE_NAME}.wiki.git wiki get-gh-pages: git clone https://github.com/Juniper/${PACKAGE_NAME}.git \ gh-pages -b gh-pages UPDATE_PACKAGE_FILE = \ -e "s;__SHA1__;$$SHA1;" \ -e "s;__SHA256__;SHA256 (textproc/${PACKAGE_FILE}) = $$SHA256;" \ -e "s;__SIZE__;SIZE (textproc/${PACKAGE_FILE}) = $$SIZE;" GH_PACKAGING_DIR = ${PACKAGE_VERSION}/packaging GH_PAGES_PACKAGE_DIR = ${GH_PAGES_DIR}/${GH_PACKAGING_DIR} packages: @-[ -d ${GH_PAGES_DIR} ] && set -x \ && echo "Updating packages on gh-pages ..." \ && mkdir -p ${GH_PAGES_DIR}/${GH_PACKAGING_DIR} \ && SHA1="`openssl sha1 ${PACKAGE_FILE} | awk '{print $$2}'`" \ && SHA256="`openssl sha256 ${PACKAGE_FILE} | awk '{print $$2}'`" \ && SIZE="`ls -l ${PACKAGE_FILE} | awk '{print $$5}'`" \ && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb ..." \ && sed ${UPDATE_PACKAGE_FILE} \ packaging/${PACKAGE_NAME}.rb.base \ > ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.rb \ && echo "... ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec ..." \ && cp packaging/${PACKAGE_NAME}.spec \ ${GH_PAGES_PACKAGE_DIR}/${PACKAGE_NAME}.spec \ && (cd ${GH_PAGES_DIR} \ && git add ${GH_PACKAGING_DIR} \ && git add ${GH_PACKAGING_DIR}/libxo.rb \ ${GH_PACKAGING_DIR}/libxo.spec \ && git commit -m 'new packaging data' \ ${GH_PACKAGING_DIR} \ && git push origin gh-pages ) ; true ANALYZE_DIR = ~/trash/libxo ANALYZE_CMD = scan-build-mp-3.6 analyze: ${MAKE} clean ${ANALYZE_CMD} -o ${ANALYZE_DIR} ${MAKE} SANIFLAGS=-fno-omit-frame-pointer -g -O2 sanitize-address: ${MAKE} clean ${MAKE} CFLAGS="-fsanitize=address ${SANIFLAGS}" ${MAKE} install ${MAKE} test sanitize-undefined: ${MAKE} clean ${MAKE} CFLAGS="-fsanitize=undefined ${SANIFLAGS}" ${MAKE} install ${MAKE} test sanitize-memory: ${MAKE} clean ${MAKE} CFLAGS="-fsanitize=memory ${SANIFLAGS}" ${MAKE} install ${MAKE} test Index: projects/make-check-sandbox/contrib/libxo/configure.ac =================================================================== --- projects/make-check-sandbox/contrib/libxo/configure.ac (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/configure.ac (revision 322022) @@ -1,498 +1,498 @@ # # $Id$ # # See ./INSTALL for more info # # # Release numbering: even numbered dot releases are official ones, and # odd numbers are development ones. The svn version of this file will # only (ONLY!) ever (EVER!) contain odd numbers, so I'll always know if # a particular user has the dist or svn release. # AC_PREREQ(2.2) -AC_INIT([libxo], [0.8.1], [phil@juniper.net]) +AC_INIT([libxo], [0.8.4], [phil@juniper.net]) AM_INIT_AUTOMAKE([-Wall -Werror foreign -Wno-portability]) # Support silent build rules. Requires at least automake-1.11. # Disable with "configure --disable-silent-rules" or "make V=1" m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) AC_PROG_CC AC_PROG_INSTALL AC_CONFIG_MACRO_DIR([m4]) AC_PROG_LN_S # Must be after AC_PROG_AR LT_INIT([dlopen shared]) AC_PATH_PROG(BASENAME, basename, /usr/bin/basename) AC_PATH_PROG(BISON, bison, /usr/bin/bison) AC_PATH_PROG(CAT, cat, /bin/cat) AC_PATH_PROG(CHMOD, chmod, /bin/chmod) AC_PATH_PROG(CP, cp, /bin/cp) AC_PATH_PROG(DIFF, diff, /usr/bin/diff) AC_PATH_PROG(MKDIR, mkdir, /bin/mkdir) AC_PATH_PROG(MV, mv, /bin/mv) AC_PATH_PROG(RM, rm, /bin/rm) AC_PATH_PROG(SED, sed, /bin/sed) AC_STDC_HEADERS # Checks for typedefs, structures, and compiler characteristics. AC_C_INLINE AC_TYPE_SIZE_T # Checks for library functions. AC_FUNC_ALLOCA AC_FUNC_MALLOC AC_FUNC_REALLOC AC_CHECK_FUNCS([bzero memmove strchr strcspn strerror strspn]) AC_CHECK_FUNCS([sranddev srand strlcpy]) AC_CHECK_FUNCS([fdopen getrusage]) AC_CHECK_FUNCS([gettimeofday ctime]) AC_CHECK_FUNCS([getpass]) AC_CHECK_FUNCS([getprogname]) AC_CHECK_FUNCS([sysctlbyname]) AC_CHECK_FUNCS([flock]) AC_CHECK_FUNCS([asprintf]) AC_CHECK_FUNCS([__flbf]) AC_CHECK_FUNCS([sysctlbyname]) AC_CHECK_HEADERS([dlfcn.h]) AC_CHECK_HEADERS([dlfcn.h]) AC_CHECK_HEADERS([stdio_ext.h]) AC_CHECK_HEADERS([tzfile.h]) AC_CHECK_HEADERS([stdtime/tzfile.h]) AC_CHECK_FUNCS([dlfunc]) AC_CHECK_HEADERS([sys/time.h]) AC_CHECK_HEADERS([ctype.h errno.h stdio.h stdlib.h]) AC_CHECK_HEADERS([string.h sys/param.h unistd.h ]) AC_CHECK_HEADERS([sys/sysctl.h]) AC_CHECK_HEADERS([threads.h]) AC_CHECK_HEADERS([monitor.h]) dnl humanize_number(3) is a great function, but it's not standard. dnl Note Macosx has the function in libutil.a but doesn't ship the dnl header file, so I'll need to carry my own implementation. See: dnl https://devforums.apple.com/thread/271121 AC_CHECK_HEADERS([libutil.h]) AC_CHECK_LIB([util], [humanize_number], [HAVE_HUMANIZE_NUMBER=$ac_cv_header_libutil_h], [HAVE_HUMANIZE_NUMBER=no]) AC_MSG_RESULT(humanize_number results: :${HAVE_HUMANIZE_NUMBER}:${ac_cv_header_libutil_h}:) if test "$HAVE_HUMANIZE_NUMBER" = "yes"; then AC_DEFINE([HAVE_HUMANIZE_NUMBER], [1], [humanize_number(3)]) fi AM_CONDITIONAL([HAVE_HUMANIZE_NUMBER], [test "$HAVE_HUMANIZE_NUMBER" = "yes"]) AC_ARG_ENABLE([gettext], [ --disable-gettext Turn off support for gettext], [GETTEXT_ENABLE=$enableval], [GETTEXT_ENABLE=yes]) dnl Looking for gettext(), assumably in libintl AC_ARG_WITH(gettext, [ --with-gettext=[PFX] Specify location of gettext installation], [GETTEXT_PREFIX=$withval], [GETTEXT_PREFIX=/usr], ) HAVE_GETTEXT=no if test "$GETTEXT_ENABLE" != "no"; then AC_MSG_CHECKING([gettext in ${GETTEXT_PREFIX}]) _save_cflags="$CFLAGS" CFLAGS="$CFLAGS -I${GETTEXT_PREFIX}/include -L${GETTEXT_PREFIX}/lib -Werror -lintl" AC_LINK_IFELSE([AC_LANG_SOURCE([[#include ] [int main() {char *cp = dgettext(NULL, "xx"); return 0; }]])], [HAVE_GETTEXT=yes], [HAVE_GETTEXT=no]) CFLAGS="$_save_cflags" AC_MSG_RESULT([$HAVE_GETTEXT]) if test "$HAVE_GETTEXT" != "yes"; then GETTEXT_PREFIX=/opt/local AC_MSG_CHECKING([gettext in ${GETTEXT_PREFIX}]) _save_cflags="$CFLAGS" CFLAGS="$CFLAGS -I${GETTEXT_PREFIX}/include -L${GETTEXT_PREFIX}/lib -Werror -lintl" AC_LINK_IFELSE([AC_LANG_SOURCE([[#include ] [int main() {char *cp = dgettext(NULL, "xx"); return 0; }]])], [HAVE_GETTEXT=yes], [HAVE_GETTEXT=no]) CFLAGS="$_save_cflags" AC_MSG_RESULT([$HAVE_GETTEXT]) fi if test "$HAVE_GETTEXT" != "yes"; then GETTEXT_PREFIX=/usr/local AC_MSG_CHECKING([gettext in ${GETTEXT_PREFIX}]) _save_cflags="$CFLAGS" CFLAGS="$CFLAGS -I${GETTEXT_PREFIX}/include -L${GETTEXT_PREFIX}/lib -Werror -lintl" AC_LINK_IFELSE([AC_LANG_SOURCE([[#include ] [int main() {char *cp = dgettext(NULL, "xx"); return 0; }]])], [HAVE_GETTEXT=yes], [HAVE_GETTEXT=no]) CFLAGS="$_save_cflags" AC_MSG_RESULT([$HAVE_GETTEXT]) fi fi if test "$HAVE_GETTEXT" = "yes"; then AC_DEFINE([HAVE_GETTEXT], [1], [gettext(3)]) GETTEXT_CFLAGS="-I${GETTEXT_PREFIX}/include" GETTEXT_LIBS="-L${GETTEXT_PREFIX}/lib -lintl" else GETTEXT_PREFIX=none GETTEXT_CFLAGS= GETTEXT_LIBS= fi AC_SUBST(GETTEXT_CFLAGS) AC_SUBST(GETTEXT_LIBS) GETTEXT_LIBDIR=${GETTEXT_PREFIX}/lib AC_SUBST(GETTEXT_LIBDIR) if test -x ${GETTEXT_PREFIX}/bin/msgfmt ; then GETTEXT_BINDIR=${GETTEXT_PREFIX}/bin elif test -x ${GETTEXT_PREFIX}/local/bin/msgfmt ; then GETTEXT_BINDIR=${GETTEXT_PREFIX}/local/bin else AC_MSG_NOTICE("could not find msgfmt tool") # Use a (bad) fall back value GETTEXT_BINDIR=${GETTEXT_PREFIX}/bin fi AC_SUBST(GETTEXT_BINDIR) AM_CONDITIONAL([HAVE_GETTEXT], [test "$HAVE_GETTEXT" = "yes"]) dnl Looking for how to do thread-local variables AC_ARG_WITH(threads, [ --with-threads=[STYLE] Specify style of thread-local support (none)], [THREAD_LOCAL=$withval], [THREAD_LOCAL=unknown], ) AC_MSG_CHECKING([thread-locals are ${THREAD_LOCAL}]) if test "$THREAD_LOCAL" = "unknown"; then AC_LINK_IFELSE([AC_LANG_SOURCE([[] [__thread int foo; int main() { foo++; return foo; }]])], [THREAD_LOCAL=before], [THREAD_LOCAL=unknown]) AC_MSG_RESULT([$THREAD_LOCAL]) fi if test "$THREAD_LOCAL" = "unknown"; then AC_LINK_IFELSE([AC_LANG_SOURCE([[] [int __thread foo; int main() { foo++; return foo; }]])], [THREAD_LOCAL=after], [THREAD_LOCAL=unknown]) AC_MSG_RESULT([$THREAD_LOCAL]) fi if test "$THREAD_LOCAL" = "unknown"; then AC_LINK_IFELSE([AC_LANG_SOURCE([[] [__declspec(int) foo; int main() { foo++; return foo; }]])], [THREAD_LOCAL=declspec], [THREAD_LOCAL=unknown]) AC_MSG_RESULT([$THREAD_LOCAL]) fi if test "$THREAD_LOCAL" != "unknown"; then AC_DEFINE_UNQUOTED([HAVE_THREAD_LOCAL], THREAD_LOCAL_${THREAD_LOCAL}, [thread-local setting]) fi dnl Looking for libcrypto.... AC_CHECK_LIB([crypto], [MD5_Init]) AM_CONDITIONAL([HAVE_LIBCRYPTO], [test "$HAVE_LIBCRYPTO" != "no"]) AC_CHECK_MEMBER([struct sockaddr_un.sun_len], [HAVE_SUN_LEN=yes ; AC_DEFINE([HAVE_SUN_LEN], [1], [Have struct sockaddr_un.sun_len])], [HAS_SUN_LEN=no], [[#include ]]) AC_CHECK_DECLS([__isthreaded], [], [], [#include ]) HAVE_ISTHREADED=${ac_cv_have_decl___isthreaded} dnl dnl Some packages need to be checked against version numbers so we dnl define a function here for later use dnl AC_DEFUN([VERSION_TO_NUMBER], [`$1 | sed -e 's/lib.* //' | awk 'BEGIN { FS = "."; } { printf "%d", ([$]1 * 1000 + [$]2) * 1000 + [$]3;}'`]) LIBSLAX_CONFIG_PREFIX="" LIBSLAX_SRC="" AC_ARG_WITH(libslax-prefix, [ --with-libslax-prefix=[PFX] Specify location of libslax config], LIBSLAX_CONFIG_PREFIX=$withval ) AC_MSG_CHECKING(for libslax) if test "x$LIBSLAX_CONFIG_PREFIX" != "x" then SLAX_CONFIG=${LIBSLAX_CONFIG_PREFIX}/bin/slax-config else SLAX_CONFIG=slax-config fi dnl dnl make sure slax-config is executable, dnl test version and init our variables dnl if ${SLAX_CONFIG} --libs > /dev/null 2>&1 then LIBSLAX_VERSION=`$SLAX_CONFIG --version` SLAX_BINDIR="`$SLAX_CONFIG --bindir | head -1`" SLAX_OXTRADOCDIR="`$SLAX_CONFIG --oxtradoc | head -1`" AC_MSG_RESULT($LIBSLAX_VERSION found) HAVE_OXTRADOC=yes else LIBSLAX_VERSION= SLAX_BINDIR= SLAX_OXTRADOCDIR= AC_MSG_RESULT([no]) HAVE_OXTRADOC=no fi AM_CONDITIONAL([HAVE_OXTRADOC], [test "$HAVE_OXTRADOC" != "no"]) AC_SUBST(SLAX_BINDIR) AC_SUBST(SLAX_OXTRADOCDIR) AC_MSG_CHECKING([whether to build with warnings]) AC_ARG_ENABLE([warnings], [ --enable-warnings Turn on compiler warnings], [LIBXO_WARNINGS=$enableval], [LIBXO_WARNINGS=no]) AC_MSG_RESULT([$LIBXO_WARNINGS]) AM_CONDITIONAL([LIBXO_WARNINGS_HIGH], [test "$LIBXO_WARNINGS" != "no"]) AC_MSG_CHECKING([whether to build with debugging]) AC_ARG_ENABLE([debug], [ --enable-debug Turn on debugging], [LIBXO_DEBUG=yes; AC_DEFINE([LIBXO_DEBUG], [1], [Enable debugging])], [LIBXO_DEBUG=no]) AC_MSG_RESULT([$LIBXO_DEBUG]) AM_CONDITIONAL([LIBXO_DEBUG], [test "$LIBXO_DEBUG" != "no"]) AC_MSG_CHECKING([whether to use int return codes]) AC_ARG_ENABLE([int-return-codes], [ --enable-int-return-codes Use int return codes (instead of ssize_t)], [USE_INT_RETURN_CODES=yes; AC_DEFINE([USE_INT_RETURN_CODES], [1], [Use int return codes])], [USE_INT_RETURN_CODES=no]) AC_MSG_RESULT([$USE_INT_RETURN_CODES]) AC_MSG_CHECKING([whether to build with text-only rendering]) AC_ARG_ENABLE([text-only], [ --enable-text-only Turn on text-only rendering], [LIBXO_TEXT_ONLY=yes; AC_DEFINE([LIBXO_TEXT_ONLY], [1], [Enable text-only rendering])], [LIBXO_TEXT_ONLY=no]) AC_MSG_RESULT([$LIBXO_TEXT_ONLY]) AM_CONDITIONAL([LIBXO_TEXT_ONLY], [test "$LIBXO_TEXT_ONLY" != "no"]) AC_MSG_CHECKING([whether to build with local wcwidth implementation]) AC_ARG_ENABLE([wcwidth], [ --disable-wcwidth Disable local wcwidth implementation], [LIBXO_WCWIDTH=$enableval], [LIBXO_WCWIDTH=yes]) AC_MSG_RESULT([$LIBXO_WCWIDTH]) if test "${LIBXO_WCWIDTH}" != "no"; then AC_DEFINE([LIBXO_WCWIDTH], [1], [Enable local wcwidth implementation]) fi AC_MSG_CHECKING([retain hash bucket size]) AC_ARG_WITH(retain-size, [ --with-retain-size=[DIR] Specify retain hash bucket size (in bits)], [XO_RETAIN_SIZE=$withval], [XO_RETAIN_SIZE=default] ) AC_MSG_RESULT([$XO_RETAIN_SIZE]) if test "${XO_RETAIN_SIZE}" != "default"; then AC_DEFINE_UNQUOTED([XO_RETAIN_SIZE], ${XO_RETAIN_SIZE}, [Retain hash bucket size]) fi AC_CHECK_LIB([m], [lrint]) AM_CONDITIONAL([HAVE_LIBM], [test "$HAVE_LIBM" != "no"]) AC_MSG_CHECKING([compiler for gcc]) HAVE_GCC=no if test "${CC}" != ""; then HAVE_GCC=`${CC} --version 2>&1 | grep GCC` if test "${HAVE_GCC}" != ""; then HAVE_GCC=yes else HAVE_GCC=no fi fi AC_MSG_RESULT([$HAVE_GCC]) AM_CONDITIONAL([HAVE_GCC], [test "$HAVE_GCC" = "yes"]) AC_MSG_CHECKING([whether to build with printflike]) AC_ARG_ENABLE([printflike], [ --enable-printflike Enable use of GCC __printflike attribute], [HAVE_PRINTFLIKE=yes; AC_DEFINE([HAVE_PRINTFLIKE], [1], [Support printflike])], [HAVE_PRINTFLIKE=no]) AC_MSG_RESULT([$HAVE_PRINTFLIKE]) AM_CONDITIONAL([HAVE_PRINTFLIKE], [test "$HAVE_PRINTFLIKE" != ""]) AC_MSG_CHECKING([whether to build with LIBXO_OPTIONS]) AC_ARG_ENABLE([libxo-options], [ --disable-libxo-options Turn off support for LIBXO_OPTIONS], [LIBXO_OPTS=$enableval], [LIBXO_OPTS=yes]) AC_MSG_RESULT([$LIBXO_OPTS]) AM_CONDITIONAL([NO_LIBXO_OPTIONS], [test "$LIBXO_OPTS" != "yes"]) case $host_os in darwin*) LIBTOOL=glibtool XO_LIBEXT=dylib ;; Linux*|linux*) CFLAGS="-D_GNU_SOURCE $CFLAGS" LDFLAGS=-ldl XO_LIBEXT=so ;; cygwin*|CYGWIN*) LDFLAGS=-no-undefined XO_LIBEXT=ddl ;; esac case $prefix in NONE) prefix=/usr/local ;; esac XO_LIBS=-lxo XO_SRCDIR=${srcdir} XO_LIBDIR=${libdir} XO_BINDIR=${bindir} XO_INCLUDEDIR=${includedir} XO_CFLAGS="${CFLAGS}" AC_SUBST(XO_LIBS) AC_SUBST(XO_SRCDIR) AC_SUBST(XO_LIBDIR) AC_SUBST(XO_BINDIR) AC_SUBST(XO_INCLUDEDIR) AC_SUBST(XO_LIBEXT) AC_SUBST(XO_CFLAGS) AC_ARG_WITH(encoder-dir, [ --with-encoder-dir=[DIR] Specify location of encoder libraries], [XO_ENCODERDIR=$withval], [XO_ENCODERDIR=$libdir/libxo/encoder] ) AC_SUBST(XO_ENCODERDIR) AC_ARG_WITH(share-dir, [ --with-share-dir=[DIR] Specify location of shared files], [XO_SHAREDIR=$withval], [XO_SHAREDIR=$datarootdir/libxo] ) XO_SHAREDIR=`echo $XO_SHAREDIR | sed "s;\\${prefix};$prefix;"` AC_SUBST(XO_SHAREDIR) dnl for the spec file RELDATE=`date +'%Y-%m-%d%n'` AC_SUBST(RELDATE) AC_MSG_RESULT(Using configure dir $ac_abs_confdir) if test -d $ac_abs_confdir/.git ; then extra=`git branch | awk '/\*/ { print $2 }'` if test "$extra" != "" -a "$extra" != "master" then LIBXO_VERSION_EXTRA="-git-$extra" fi fi LIBXO_VERSION=$PACKAGE_VERSION LIBXO_VERSION_NUMBER=VERSION_TO_NUMBER(echo $PACKAGE_VERSION) AC_SUBST(LIBXO_VERSION) AC_SUBST(LIBXO_VERSION_NUMBER) AC_SUBST(LIBXO_VERSION_EXTRA) AC_DEFINE_UNQUOTED(LIBXO_VERSION, ["$LIBXO_VERSION"], [Version number as dotted value]) AC_DEFINE_UNQUOTED(LIBXO_VERSION_NUMBER, [$LIBXO_VERSION_NUMBER], [Version number as a number]) AC_DEFINE_UNQUOTED(LIBXO_VERSION_STRING, ["$LIBXO_VERSION_NUMBER"], [Version number as string]) AC_DEFINE_UNQUOTED(LIBXO_VERSION_EXTRA, ["$LIBXO_VERSION_EXTRA"], [Version number extra information]) AC_CONFIG_HEADERS([libxo/xo_config.h]) AC_CONFIG_FILES([ Makefile libxo-config xohtml/xohtml.sh libxo/Makefile libxo/add.man encoder/Makefile encoder/cbor/Makefile encoder/test/Makefile xo/Makefile xolint/Makefile xohtml/Makefile xopo/Makefile packaging/libxo.pc doc/Makefile tests/Makefile tests/core/Makefile tests/gettext/Makefile tests/xo/Makefile packaging/libxo.spec packaging/libxo.rb.base ]) AC_OUTPUT AC_MSG_NOTICE([summary of build options: libxo version: ${VERSION} ${LIBXO_VERSION_EXTRA} host type: ${host} / ${host_os} install prefix: ${prefix} srcdir: ${XO_SRCDIR} libdir: ${XO_LIBDIR} bindir: ${XO_BINDIR} includedir: ${XO_INCLUDEDIR} share dir: ${XO_SHAREDIR} extensions dir: ${XO_ENCODERDIR} oxtradoc dir: ${SLAX_OXTRADOCDIR} compiler: ${CC} (${HAVE_GCC:-no}) compiler flags: ${CFLAGS} library types: Shared=${enable_shared}, Static=${enable_static} warnings: ${LIBXO_WARNINGS:-no} debug: ${LIBXO_DEBUG:-no} printf-like: ${HAVE_PRINTFLIKE:-no} libxo-options: ${LIBXO_OPTS:-no} text-only: ${LIBXO_TEXT_ONLY:-no} gettext: ${HAVE_GETTEXT:-no} (${GETTEXT_PREFIX}) isthreaded: ${HAVE_ISTHREADED:-no} thread-local: ${THREAD_LOCAL:-no} local wcwidth: ${LIBXO_WCWIDTH:-no} retain size: ${XO_RETAIN_SIZE:-no} ]) Index: projects/make-check-sandbox/contrib/libxo/doc/libxo-manual.html =================================================================== --- projects/make-check-sandbox/contrib/libxo/doc/libxo-manual.html (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/doc/libxo-manual.html (revision 322022) @@ -1,27436 +1,27436 @@ libxo: The Easy Way to Generate text, XML, JSON, and HTML output

libxo: The Easy Way to Generate text, XML, JSON, and HTML output
libxo-manual

Table of Contents


1_ 
Overview

libxo - A Library for Generating Text, XML, JSON, and HTML Output

You want to prepare for the future, but you need to live in the present. You'd love a flying car, but need to get to work today. You want to support features like XML, JSON, and HTML rendering to allow integration with NETCONF, REST, and web browsers, but you need to make text output for command line users.

And you don't want multiple code paths that can't help but get out of sync:

     /* None of this "if (xml) {... } else {...}"  logic */
     if (xml) {
         /* some code to make xml*/
     } else {
         /* other code to make text */
         /* oops forgot to add something on both clauses! */
     }
 
     /* And ifdefs are right out. */
     #ifdef MAKE_XML
         /* icky */
     #else
         /* pooh */
     #endif
 	    

But you'd really, really like all the fancy features that modern encoding formats can provide. libxo can help.

The libxo library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application decides at run time which output style should be produced. The application calls a function "xo_emit" to product output that is described in a format string. A "field descriptor" tells libxo what the field is and what it means. Each field descriptor is placed in braces with a printf-like format string (Section 3.2):

     xo_emit(" {:lines/%7ju} {:words/%7ju} "
             "{:characters/%7ju} {d:filename/%s}\n",
             linect, wordct, charct, file);
 	    

Each field can have a role, with the 'value' role being the default, and the role tells libxo how and when to render that field (see Section 3.2.1 for details). Modifiers change how the field is rendered in different output styles (see Section 3.2.2 for details. Output can then be generated in various style, using the "‑‑libxo" option:

     % wc /etc/motd
           25     165    1140 /etc/motd
     % wc --libxo xml,pretty,warn /etc/motd
     <wc>
       <file>
         <lines>25</lines>
         <words>165</words>
         <characters>1140</characters>
         <filename>/etc/motd</filename>
       </file>
     </wc>
     % wc --libxo json,pretty,warn /etc/motd
     {
       "wc": {
         "file": [
           {
             "lines": 25,
             "words": 165,
             "characters": 1140,
             "filename": "/etc/motd"
           }
         ]
       }
     }
     % wc --libxo html,pretty,warn /etc/motd
     <div class="line">
       <div class="text"> </div>
       <div class="data" data-tag="lines">     25</div>
       <div class="text"> </div>
       <div class="data" data-tag="words">    165</div>
       <div class="text"> </div>
       <div class="data" data-tag="characters">   1140</div>
       <div class="text"> </div>
       <div class="data" data-tag="filename">/etc/motd</div>
     </div>
 	    

Same code path, same format strings, same information, but it's rendered in distinct styles based on run-time flags.


2_ 
Getting libxo

libxo now ships as part of the FreeBSD Operating System (as of -11).

libxo lives on github as:

https://github.com/Juniper/libxo

The latest release of libxo is available at:

https://github.com/Juniper/libxo/releases

We are following the branching scheme from http://nvie.com/posts/a-successful-git-branching-model/ which means we will do development under the "develop" branch, and release from the "master" branch. To clone a developer tree, run the following command:

   git clone https://github.com/Juniper/libxo.git -b develop
 	    

We're using semantic release numbering, as defined in http://semver.org/spec/v2.0.0.html.

libxo is open source, distributed under the BSD license. It shipped as part of the FreeBSD operating system starting with release 11.0.

Issues, problems, and bugs should be directly to the issues page on our github site.

Section Contents:

2.1 
Downloading libxo Source Code

You can retrieve the source for libxo in two ways:

A) Use a "distfile" for a specific release. We use github to maintain our releases. Visit github release page (https://github.com/Juniper/libxo/releases) to see the list of releases. To download the latest, look for the release with the green "Latest release" button and the green "libxo‑RELEASE.tar.gz" button under that section.

After downloading that release's distfile, untar it as follows:

     tar -zxf libxo-RELEASE.tar.gz
     cd libxo-RELEASE
 	    

[Note: for Solaris users, your "tar" command lacks the "‑z" flag, so you'll need to substitute "gzip -dc "file" | tar xf -" instead of "tar -zxf "file"".]

B) Use the current build from github. This gives you the most recent source code, which might be less stable than a specific release. To build libxo from the git repo:

     git clone https://github.com/Juniper/libxo.git
     cd libxo
 	    

_BE AWARE_: The github repository does _not_ contain the files generated by "autoreconf", with the notable exception of the "m4" directory. Since these files (depcomp, configure, missing, install-sh, etc) are generated files, we keep them out of the source code repository.

This means that if you download the a release distfile, these files will be ready and you'll just need to run "configure", but if you download the source code from svn, then you'll need to run "autoreconf" by hand. This step is done for you by the "setup.sh" script, described in the next section.

2.2 
Building libxo

To build libxo, you'll need to set up the build, run the "configure" script, run the "make" command, and run the regression tests.

The following is a summary of the commands needed. These commands are explained in detail in the rest of this section.

     sh bin/setup.sh
     cd build
     ../configure
     make
     make test
     sudo make install
 	    

The following sections will walk through each of these steps with additional details and options, but the above directions should be all that's needed.

Section Contents:

Setting up the build

[If you downloaded a distfile, you can skip this step.]

Run the "setup.sh" script to set up the build. This script runs the "autoreconf" command to generate the "configure" script and other generated files.

     sh bin/setup.sh
 	    

Note: We're are currently using autoreconf version 2.69.

Running the "configure" Script

Configure (and autoconf in general) provides a means of building software in diverse environments. Our configure script supports a set of options that can be used to adjust to your operating environment. Use "configure --help" to view these options.

We use the "build" directory to keep object files and generated files away from the source tree.

To run the configure script, change into the "build" directory, and run the "configure" script. Add any required options to the "../configure" command line.

     cd build
     ../configure
 	    

Expect to see the "configure" script generate the following error:

     /usr/bin/rm: cannot remove `libtoolT': No such file or directory
 	    

This error is harmless and can be safely ignored.

By default, libxo installs architecture-independent files, including extension library files, in the /usr/local directories. To specify an installation prefix other than /usr/local for all installation files, include the --prefix=prefix option and specify an alternate location. To install just the extension library files in a different, user-defined location, include the --with-extensions-dir=dir option and specify the location where the extension libraries will live.

     cd build
     ../configure [OPTION]... [VAR=VALUE]...
 	    

Section Contents:

Running the "make" command

Once the "configure" script is run, build the images using the "make" command:

     make
 	    

Running the Regression Tests

libxo includes a set of regression tests that can be run to ensure the software is working properly. These test are optional, but will help determine if there are any issues running libxo on your machine. To run the regression tests:

     make test
 	    

Installing libxo

Once the software is built, you'll need to install libxo using the "make install" command. If you are the root user, or the owner of the installation directory, simply issue the command:

     make install
 	    

If you are not the "root" user and are using the "sudo" package, use:

     sudo make install
 	    

Verify the installation by viewing the output of "xo --version":

     % xo --version
     libxo version 0.3.5-git-develop
     xo version 0.3.5-git-develop
 	    

3_ 
Formatting with libxo

Most unix commands emit text output aimed at humans. It is designed to be parsed and understood by a user. Humans are gifted at extracting details and pattern matching in such output. Often programmers need to extract information from this human-oriented output. Programmers use tools like grep, awk, and regular expressions to ferret out the pieces of information they need. Such solutions are fragile and require maintenance when output contents change or evolve, along with testing and validation.

Modern tool developers favor encoding schemes like XML and JSON, which allow trivial parsing and extraction of data. Such formats are simple, well understood, hierarchical, easily parsed, and often integrate easier with common tools and environments. Changes to content can be done in ways that do not break existing users of the data, which can reduce maintenance costs and increase feature velocity.

In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable.

libxo allows a single set of function calls in source code to generate traditional text output, as well as XML and JSON formatted data. HTML can also be generated; "<div>" elements surround the traditional text output, with attributes that detail how to render the data.

A single libxo function call in source code is all that's required:

     xo_emit("Connecting to {:host}.{:domain}...\n", host, domain);
 
     TEXT:
       Connecting to my-box.example.com...
     XML:
       <host>my-box</host>
       <domain>example.com</domain>
     JSON:
       "host": "my-box",
       "domain": "example.com"
     HTML:
        <div class="line">
          <div class="text">Connecting to </div>
          <div class="data" data-tag="host" 
               data-xpath="/top/host">my-box</div>
          <div class="text">.</div>
          <div class="data" data-tag="domain"
               data-xpath="/top/domain">example.com</div>
          <div class="text">...</div>
        </div>
 	    

Section Contents:

3.1 
Encoding Styles

There are four encoding styles supported by libxo:

  • TEXT output can be display on a terminal session, allowing compatibility with traditional command line usage.
  • XML output is suitable for tools like XPath and protocols like NETCONF.
  • JSON output can be used for RESTful APIs and integration with languages like Javascript and Python.
  • HTML can be matched with a small CSS file to permit rendering in any HTML5 browser.

In general, XML and JSON are suitable for encoding data, while TEXT is suited for terminal output and HTML is suited for display in a web browser (see Section 8).

Section Contents:

Text Output

Most traditional programs generate text output on standard output, with contents like:

     36      ./src
     40      ./bin
     90      .
 	    

In this example (taken from du source code), the code to generate this data might look like:

     printf("%d\t%s\n", num_blocks, path);
 	    

Simple, direct, obvious. But it's only making text output. Imagine using a single code path to make TEXT, XML, JSON or HTML, deciding at run time which to generate.

libxo expands on the idea of printf format strings to make a single format containing instructions for creating multiple output styles:

     xo_emit("{:blocks/%d}\t{:path/%s}\n", num_blocks, path);
 	    

This line will generate the same text output as the earlier printf call, but also has enough information to generate XML, JSON, and HTML.

The following sections introduce the other formats.

XML Output

XML output consists of a hierarchical set of elements, each encoded with a start tag and an end tag. The element should be named for data value that it is encoding:

     <item>
       <blocks>36</blocks>
       <path>./src</path>
     </item>
     <item>
       <blocks>40</blocks>
       <path>./bin</path>
     </item>
     <item>
       <blocks>90</blocks>
       <path>.</path>
     </item>
 	    

XML is a W3C standard for encoding data. See w3c.org/TR/xml for additional information.

JSON Output

JSON output consists of a hierarchical set of objects and lists, each encoded with a quoted name, a colon, and a value. If the value is a string, it must be quoted, but numbers are not quoted. Objects are encoded using braces; lists are encoded using square brackets. Data inside objects and lists is separated using commas:

     items: [
         { "blocks": 36, "path" : "./src" },
         { "blocks": 40, "path" : "./bin" },
         { "blocks": 90, "path" : "./" }
     ]
 	    

HTML Output

HTML output is designed to allow the output to be rendered in a web browser with minimal effort. Each piece of output data is rendered inside a <div> element, with a class name related to the role of the data. By using a small set of class attribute values, a CSS stylesheet can render the HTML into rich text that mirrors the traditional text content.

Additional attributes can be enabled to provide more details about the data, including data type, description, and an XPath location.

     <div class="line">
       <div class="data" data-tag="blocks">36</div>
       <div class="padding">      </div>
       <div class="data" data-tag="path">./src</div>
     </div>
     <div class="line">
       <div class="data" data-tag="blocks">40</div>
       <div class="padding">      </div>
       <div class="data" data-tag="path">./bin</div>
     </div>
     <div class="line">
       <div class="data" data-tag="blocks">90</div>
       <div class="padding">      </div>
       <div class="data" data-tag="path">./</div>
     </div>
 	    

3.2 
Format Strings

libxo uses format strings to control the rendering of data into the various output styles. Each format string contains a set of zero or more field descriptions, which describe independent data fields. Each field description contains a set of modifiers, a content string, and zero, one, or two format descriptors. The modifiers tell libxo what the field is and how to treat it, while the format descriptors are formatting instructions using printf-style format strings, telling libxo how to format the field. The field description is placed inside a set of braces, with a colon (":") after the modifiers and a slash ("/") before each format descriptors. Text may be intermixed with field descriptions within the format string.

The field description is given as follows:

     '{' [ role | modifier ]* [',' long-names ]* ':' [ content ]
             [ '/' field-format [ '/' encoding-format ]] '}'
 	    

The role describes the function of the field, while the modifiers enable optional behaviors. The contents, field-format, and encoding-format are used in varying ways, based on the role. These are described in the following sections.

In the following example, three field descriptors appear. The first is a padding field containing three spaces of padding, the second is a label ("In stock"), and the third is a value field ("in‑stock"). The in-stock field has a "%u" format that will parse the next argument passed to the xo_emit function as an unsigned integer.

     xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 65);
 	    

This single line of code can generate text (" In stock: 65\n"), XML ("<in‑stock>65</in‑stock>"), JSON ('"in‑stock": 6'), or HTML (too lengthy to be listed here).

While roles and modifiers typically use single character for brevity, there are alternative names for each which allow more verbose formatting strings. These names must be preceded by a comma, and may follow any single-character values:

     xo_emit("{L,white,colon:In stock}{,key:in-stock/%u}\n", 65);
 	    

Section Contents:

Field Roles

Field roles are optional, and indicate the role and formatting of the content. The roles are listed below; only one role is permitted:

R Name Description
C color Field has color and effect controls
D decoration Field is non-text (e.g., colon, comma)
E error Field is an error message
G gettext Call gettext(3) on the format string
L label Field is text that prefixes a value
N note Field is text that follows a value
P padding Field is spaces needed for vertical alignment
T title Field is a title value for headings
U units Field is the units for the previous value field
V value Field is the name of field (the default)
W warning Field is a warning message
[ start-anchor Begin a section of anchored variable-width text
] stop-anchor End a section of anchored variable-width text
     EXAMPLE:
         xo_emit("{L:Free}{D::}{P:   }{:free/%u} {U:Blocks}\n",
                 free_blocks);
 	    

When a role is not provided, the "value" role is used as the default.

Roles and modifiers can also use more verbose names, when preceded by a comma:

     EXAMPLE:
         xo_emit("{,label:Free}{,decoration::}{,padding:   }"
                 "{,value:free/%u} {,units:Blocks}\n",
                 free_blocks);
 	    

Section Contents:

The Color Role ({C:})

Colors and effects control how text values are displayed; they are used for display styles (TEXT and HTML).

     xo_emit("{C:bold}{:value}{C:no-bold}\n", value);
 	    

Colors and effects remain in effect until modified by other "C"-role fields.

     xo_emit("{C:bold}{C:inverse}both{C:no-bold}only inverse\n");
 	    

If the content is empty, the "reset" action is performed.

     xo_emit("{C:both,underline}{:value}{C:}\n", value);
 	    

The content should be a comma-separated list of zero or more colors or display effects.

     xo_emit("{C:bold,inverse}Ugly{C:no-bold,no-inverse}\n");
 	    

The color content can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):

    xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "",
            need_underline ? "underline" : "", value);
 	    

Color names are prefixed with either "fg‑" or "bg‑" to change the foreground and background colors, respectively.

     xo_emit("{C:/fg-%s,bg-%s}{Lwc:Cost}{:cost/%u}{C:reset}\n",
             fg_color, bg_color, cost);
 	    

The following table lists the supported effects:

Name Description
bg-XXXXX Change background color
bold Start bold text effect
fg-XXXXX Change foreground color
inverse Start inverse (aka reverse) text effect
no-bold Stop bold text effect
no-inverse Stop inverse (aka reverse) text effect
no-underline Stop underline text effect
normal Reset effects (only)
reset Reset colors and effects (restore defaults)
underline Start underline text effect

The following color names are supported:

Name Description
black
blue
cyan
default Default color for foreground or background
green
magenta
red
white
yellow

When using colors, the developer should remember that users will change the foreground and background colors of terminal session according to their own tastes, so assuming that "blue" looks nice is never safe, and is a constant annoyance to your dear author. In addition, a significant percentage of users (1 in 12) will be color blind. Depending on color to convey critical information is not a good idea. Color should enhance output, but should not be used as the sole means of encoding information.

The Decoration Role ({D:})

Decorations are typically punctuation marks such as colons, semi-colons, and commas used to decorate the text and make it simpler for human readers. By marking these distinctly, HTML usage scenarios can use CSS to direct their display parameters.

     xo_emit("{D:((}{:name}{D:))}\n", name);
 	    

The Gettext Role ({G:})

libxo supports internationalization (i18n) through its use of gettext(3). Use the "{G:}" role to request that the remaining part of the format string, following the "{G:}" field, be handled using gettext().

Since gettext() uses the string as the key into the message catalog, libxo uses a simplified version of the format string that removes unimportant field formatting and modifiers, stopping minor formatting changes from impacting the expensive translation process. A developer change such as changing "/%06d" to "/%08d" should not force hand inspection of all .po files.

The simplified version can be generated for a single message using the "xopo -s <text>" command, or an entire .pot can be translated using the "xopo -f <input> -o <output>" command.

    xo_emit("{G:}Invalid token\n");
 	    

The {G:} role allows a domain name to be set. gettext calls will continue to use that domain name until the current format string processing is complete, enabling a library function to emit strings using it's own catalog. The domain name can be either static as the content of the field, or a format can be used to get the domain name from the arguments.

    xo_emit("{G:libc}Service unavailable in restricted mode\n");
 	    

See Section 11.5 for additional details.

The Label Role ({L:})

Labels are text that appears before a value.

     xo_emit("{Lwc:Cost}{:cost/%u}\n", cost);
 	    

The Note Role ({N:})

Notes are text that appears after a value.

     xo_emit("{:cost/%u} {N:per year}\n", cost);
 	    

The Padding Role ({P:})

Padding represents whitespace used before and between fields.

The padding content can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):

     xo_emit("{P:        }{Lwc:Cost}{:cost/%u}\n", cost);
     xo_emit("{P:/%30s}{Lwc:Cost}{:cost/%u}\n", "", cost);
 	    

The Title Role ({T:})

Title are heading or column headers that are meant to be displayed to the user. The title can be either static, when placed directly within the field descriptor, or a printf-style format descriptor can be used, if preceded by a slash ("/"):

     xo_emit("{T:Interface Statistics}\n");
     xo_emit("{T:/%20.20s}{T:/%6.6s}\n", "Item Name", "Cost");
 	    

Title fields have an extra convenience feature; if both content and format are specified, instead of looking to the argument list for a value, the content is used, allowing a mixture of format and content within the field descriptor:

     xo_emit("{T:Name/%20s}{T:Count/%6s}\n");
 	    

Since the incoming argument is a string, the format must be "%s" or something suitable.

The Units Role ({U:})

Units are the dimension by which values are measured, such as degrees, miles, bytes, and decibels. The units field carries this information for the previous value field.

     xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\n", miles);
 	    

Note that the sense of the 'w' modifier is reversed for units; a blank is added before the contents, rather than after it.

When the XOF_UNITS flag is set, units are rendered in XML as the "units" attribute:

     <distance units="miles">50</distance>
 	    

Units can also be rendered in HTML as the "data‑units" attribute:

     <div class="data" data-tag="distance" data-units="miles"
          data-xpath="/top/data/distance">50</div>
 	    

The Value Role ({V:} and {:})

The value role is used to represent the a data value that is interesting for the non-display output styles (XML and JSON). Value is the default role; if no other role designation is given, the field is a value. The field name must appear within the field descriptor, followed by one or two format descriptors. The first format descriptor is used for display styles (TEXT and HTML), while the second one is used for encoding styles (XML and JSON). If no second format is given, the encoding format defaults to the first format, with any minimum width removed. If no first format is given, both format descriptors default to "%s".

     xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\n",
             length, width, height);
     xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\n,
             author, poem, year);
 	    

The Anchor Roles ({[:} and {]:})

The anchor roles allow a set of strings by be padded as a group, but still be visible to xo_emit as distinct fields. Either the start or stop anchor can give a field width and it can be either directly in the descriptor or passed as an argument. Any fields between the start and stop anchor are padded to meet the minimum width given.

To give a width directly, encode it as the content of the anchor tag:

     xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\n", min, max);
 	    

To pass a width as an argument, use "%d" as the format, which must appear after the "/". Note that only "%d" is supported for widths. Using any other value could ruin your day.

     xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\n", width, min, max);
 	    

If the width is negative, padding will be added on the right, suitable for left justification. Otherwise the padding will be added to the left of the fields between the start and stop anchors, suitable for right justification. If the width is zero, nothing happens. If the number of columns of output between the start and stop anchors is less than the absolute value of the given width, nothing happens.

Widths over 8k are considered probable errors and not supported. If XOF_WARN is set, a warning will be generated.

Field Modifiers

Field modifiers are flags which modify the way content emitted for particular output styles:

M Name Description
a argument The content appears as a 'const char *' argument
c colon A colon (":") is appended after the label
d display Only emit field for display styles (text/HTML)
e encoding Only emit for encoding styles (XML/JSON)
g gettext Call gettext on field's render content
h humanize (hn) Format large numbers in human-readable style
hn-space Humanize: Place space between numeric and unit
hn-decimal Humanize: Add a decimal digit, if number < 10
hn-1000 Humanize: Use 1000 as divisor instead of 1024
k key Field is a key, suitable for XPath predicates
l leaf-list Field is a leaf-list
n no-quotes Do not quote the field when using JSON style
p plural Gettext: Use comma-separated plural form
q quotes Quote the field when using JSON style
t trim Trim leading and trailing whitespace
w white A blank (" ") is appended after the label

Roles and modifiers can also use more verbose names, when preceded by a comma. For example, the modifier string "Lwc" (or "L,white,colon") means the field has a label role (text that describes the next field) and should be followed by a colon ('c') and a space ('w'). The modifier string "Vkq" (or ":key,quote") means the field has a value role (the default role), that it is a key for the current instance, and that the value should be quoted when encoded for JSON.

Section Contents:

The Argument Modifier ({a:})

The argument modifier indicates that the content of the field descriptor will be placed as a UTF-8 string (const char *) argument within the xo_emit parameters.

     EXAMPLE:
       xo_emit("{La:} {a:}\n", "Label text", "label", "value");
     TEXT:
       Label text value
     JSON:
       "label": "value"
     XML:
       <label>value</label>
 	    

The argument modifier allows field names for value fields to be passed on the stack, avoiding the need to build a field descriptor using snprintf. For many field roles, the argument modifier is not needed, since those roles have specific mechanisms for arguments, such as "{C:fg‑%s}".

The Colon Modifier ({c:})

The colon modifier appends a single colon to the data value:

     EXAMPLE:
       xo_emit("{Lc:Name}{:name}\n", "phil");
     TEXT:
       Name:phil
 	    

The colon modifier is only used for the TEXT and HTML output styles. It is commonly combined with the space modifier ('{w:}'). It is purely a convenience feature.

The Display Modifier ({d:})

The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.

     EXAMPLE:
       xo_emit("{Lcw:Name}{d:name} {:id/%d}\n", "phil", 1);
     TEXT:
       Name: phil 1
     XML:
       <id>1</id>
 	    

The display modifier is the opposite of the encoding modifier, and they are often used to give to distinct views of the underlying data.

The Encoding Modifier ({e:})

The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML.

     EXAMPLE:
       xo_emit("{Lcw:Name}{:name} {e:id/%d}\n", "phil", 1);
     TEXT:
       Name: phil
     XML:
       <name>phil</name><id>1</id>
 	    

The encoding modifier is the opposite of the display modifier, and they are often used to give to distinct views of the underlying data.

The Gettext Modifier ({g:})

The gettext modifier is used to translate individual fields using the gettext domain (typically set using the "{G:}" role) and current language settings. Once libxo renders the field value, it is passed to gettext(3), where it is used as a key to find the native language translation.

In the following example, the strings "State" and "full" are passed to gettext() to find locale-based translated strings.

     xo_emit("{Lgwc:State}{g:state}\n", "full");
 	    

See Section 3.2.1.3, Section 3.2.2.10, and Section 11.5 for additional details.

The Humanize Modifier ({h:})

The humanize modifier is used to render large numbers as in a human-readable format. While numbers like "44470272" are completely readable to computers and savants, humans will generally find "44M" more meaningful.

"hn" can be used as an alias for "humanize".

The humanize modifier only affects display styles (TEXT and HMTL). The "no‑humanize" option (See Section 4) will block the function of the humanize modifier.

There are a number of modifiers that affect details of humanization. These are only available in as full names, not single characters. The "hn‑space" modifier places a space between the number and any multiplier symbol, such as "M" or "K" (ex: "44 K"). The "hn‑decimal" modifier will add a decimal point and a single tenths digit when the number is less than 10 (ex: "4.4K"). The "hn‑1000" modifier will use 1000 as divisor instead of 1024, following the JEDEC-standard instead of the more natural binary powers-of-two tradition.

     EXAMPLE:
         xo_emit("{h:input/%u}, {h,hn-space:output/%u}, "
             "{h,hn-decimal:errors/%u}, {h,hn-1000:capacity/%u}, "
             "{h,hn-decimal:remaining/%u}\n",
             input, output, errors, capacity, remaining);
     TEXT:
         21, 57 K, 96M, 44M, 1.2G
 	    

In the HTML style, the original numeric value is rendered in the "data‑number" attribute on the <div> element:

     <div class="data" data-tag="errors"
          data-number="100663296">96M</div>
 	    

The Key Modifier ({k:})

The key modifier is used to indicate that a particular field helps uniquely identify an instance of list data.

     EXAMPLE:
         xo_open_list("user");
         for (i = 0; i < num_users; i++) {
             xo_open_instance("user");
             xo_emit("User {k:name} has {:count} tickets\n",
                user[i].u_name, user[i].u_tickets);
             xo_close_instance("user");
         }
         xo_close_list("user");
 	    

Currently the key modifier is only used when generating XPath value for the HTML output style when XOF_XPATH is set, but other uses are likely in the near future.

The Leaf-List Modifier ({l:})

The leaf-list modifier is used to distinguish lists where each instance consists of only a single value. In XML, these are rendered as single elements, where JSON renders them as arrays.

     EXAMPLE:
         for (i = 0; i < num_users; i++) {
             xo_emit("Member {l:user}\n", user[i].u_name);
         }
     XML:
         <user>phil</user>
         <user>pallavi</user>
     JSON:
         "user": [ "phil", "pallavi" ]
 	    

The name of the field must match the name of the leaf list.

The No-Quotes Modifier ({n:})

The no-quotes modifier (and its twin, the 'quotes' modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string value, but no quotes for numeric, boolean, and null data. xo_emit applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller.

     EXAMPLE:
       const char *bool = is_true ? "true" : "false";
       xo_emit("{n:fancy/%s}", bool);
     JSON:
       "fancy": true
 	    

The Plural Modifier ({p:})

The plural modifier selects the appropriate plural form of an expression based on the most recent number emitted and the current language settings. The contents of the field should be the singular and plural English values, separated by a comma:

     xo_emit("{:bytes} {Ngp:byte,bytes}\n", bytes);
 	    

The plural modifier is meant to work with the gettext modifier ({g:}) but can work independently. See Section 3.2.2.5.

When used without the gettext modifier or when the message does not appear in the message catalog, the first token is chosen when the last numeric value is equal to 1; otherwise the second value is used, mimicking the simple pluralization rules of English.

When used with the gettext modifier, the ngettext(3) function is called to handle the heavy lifting, using the message catalog to convert the singular and plural forms into the native language.

The Quotes Modifier ({q:})

The quotes modifier (and its twin, the 'no‑quotes' modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string value, but no quotes for numeric, boolean, and null data. xo_emit applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller.

     EXAMPLE:
       xo_emit("{q:time/%d}", 2014);
     JSON:
       "year": "2014"
 	    

The heuristic is based on the format; if the format uses any of the following conversion specifiers, then no quotes are used:

     d i o u x X D O U e E f F g G a A c C p
 	    

The Trim Modifier ({t:})

The trim modifier removes any leading or trailing whitespace from the value.

     EXAMPLE:
       xo_emit("{t:description}", "   some  input   ");
     JSON:
       "description": "some input"
 	    

The White Space Modifier ({w:})

The white space modifier appends a single space to the data value:

     EXAMPLE:
       xo_emit("{Lw:Name}{:name}\n", "phil");
     TEXT:
       Name phil
 	    

The white space modifier is only used for the TEXT and HTML output styles. It is commonly combined with the colon modifier ('{c:}'). It is purely a convenience feature.

Note that the sense of the 'w' modifier is reversed for the units role ({Uw:}); a blank is added before the contents, rather than after it.

Field Formatting

The field format is similar to the format string for printf(3). Its use varies based on the role of the field, but generally is used to format the field's contents.

If the format string is not provided for a value field, it defaults to "%s".

Note a field definition can contain zero or more printf-style 'directives', which are sequences that start with a '%' and end with one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive is matched by one of more arguments to the xo_emit function.

The format string has the form:

   '%' format-modifier * format-character
 	    

The format- modifier can be:

  • a '#' character, indicating the output value should be prefixed with '0x', typically to indicate a base 16 (hex) value.
  • a minus sign ('‑'), indicating the output value should be padded on the right instead of the left.
  • a leading zero ('0') indicating the output value should be padded on the left with zeroes instead of spaces (' ').
  • one or more digits ('0' - '9') indicating the minimum width of the argument. If the width in columns of the output value is less than the minimum width, the value will be padded to reach the minimum.
  • a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum width for a non-string argument. When handling ASCII strings this functions as the field width but for multi-byte characters, a single character may be composed of multiple bytes. xo_emit will never dereference memory beyond the given number of bytes.
  • a second period followed by one or more digits indicating the maximum width for a string argument. This modifier cannot be given for non-string arguments.
  • one or more 'h' characters, indicating shorter input data.
  • one or more 'l' characters, indicating longer input data.
  • a 'z' character, indicating a 'size_t' argument.
  • a 't' character, indicating a 'ptrdiff_t' argument.
  • a ' ' character, indicating a space should be emitted before positive numbers.
  • a '+' character, indicating sign should emitted before any number.

Note that 'q', 'D', 'O', and 'U' are considered deprecated and will be removed eventually.

The format character is described in the following table:

Ltr Argument Type Format
d int base 10 (decimal)
i int base 10 (decimal)
o int base 8 (octal)
u unsigned base 10 (decimal)
x unsigned base 16 (hex)
X unsigned long base 16 (hex)
D long base 10 (decimal)
O unsigned long base 8 (octal)
U unsigned long base 10 (decimal)
e double [-]d.ddde+-dd
E double [-]d.dddE+-dd
f double [-]ddd.ddd
F double [-]ddd.ddd
g double as 'e' or 'f'
G double as 'E' or 'F'
a double [-]0xh.hhhp[+-]d
A double [-]0Xh.hhhp[+-]d
c unsigned char a character
C wint_t a character
s char * a UTF-8 string
S wchar_t * a unicode/WCS string
p void * '%#lx'

The 'h' and 'l' modifiers affect the size and treatment of the argument:

Mod d, i o, u, x, X
hh signed char unsigned char
h short unsigned short
l long unsigned long
ll long long unsigned long long
j intmax_t uintmax_t
t ptrdiff_t ptrdiff_t
z size_t size_t
q quad_t u_quad_t

UTF-8 and Locale Strings

For strings, the 'h' and 'l' modifiers affect the interpretation of the bytes pointed to argument. The default '%s' string is a 'char *' pointer to a string encoded as UTF-8. Since UTF-8 is compatible with ASCII data, a normal 7-bit ASCII string can be used. '%ls' expects a 'wchar_t *' pointer to a wide-character string, encoded as a 32-bit Unicode values. '%hs' expects a 'char *' pointer to a multi-byte string encoded with the current locale, as given by the LC_CTYPE, LANG, or LC_ALL environment varibles. The first of this list of variables is used and if none of the variables are set, the locale defaults to "UTF‑8".

libxo will convert these arguments as needed to either UTF-8 (for XML, JSON, and HTML styles) or locale-based strings for display in text style.

    xo_emit("All strings are utf-8 content {:tag/%ls}",
            L"except for wide strings");
 	    

"%S" is equivalent to "%ls".

Format Argument Type Argument Contents
%s const char * UTF-8 string
%S const char * UTF-8 string (alias for '%s')
%ls const wchar_t * Wide character UNICODE string
%hs const char * locale-based string

For example, a function is passed a locale-base name, a hat size, and a time value. The hat size is formatted in a UTF-8 (ASCII) string, and the time value is formatted into a wchar_t string.

     void print_order (const char *name, int size,
                       struct tm *timep) {
         char buf[32];
         const char *size_val = "unknown";
 
         if (size > 0)
             snprintf(buf, sizeof(buf), "%d", size);
             size_val = buf;
         }
 
         wchar_t when[32];
         wcsftime(when, sizeof(when), L"%d%b%y", timep);
 
         xo_emit("The hat for {:name/%hs} is {:size/%s}.\n",
                 name, size_val);
         xo_emit("It was ordered on {:order-time/%ls}.\n",
                 when);
     }
 	    

It is important to note that xo_emit will perform the conversion required to make appropriate output. Text style output uses the current locale (as described above), while XML, JSON, and HTML use UTF-8.

UTF-8 and locale-encoded strings can use multiple bytes to encode one column of data. The traditional "precision'" (aka "max‑width") value for "%s" printf formatting becomes overloaded since it specifies both the number of bytes that can be safely referenced and the maximum number of columns to emit. xo_emit uses the precision as the former, and adds a third value for specifying the maximum number of columns.

In this example, the name field is printed with a minimum of 3 columns and a maximum of 6. Up to ten bytes of data at the location given by 'name' are in used in filling those columns.

     xo_emit("{:name/%3.10.6s}", name);
 	    

Characters Outside of Field Definitions

Characters in the format string that are not part of a field definition are copied to the output for the TEXT style, and are ignored for the JSON and XML styles. For HTML, these characters are placed in a <div> with class "text".

   EXAMPLE:
       xo_emit("The hat is {:size/%s}.\n", size_val);
   TEXT:
       The hat is extra small.
   XML:
       <size>extra small</size>
   JSON:
       "size": "extra small"
   HTML:
       <div class="text">The hat is </div>
       <div class="data" data-tag="size">extra small</div>
       <div class="text">.</div>
 	    

"%m" Is Supported

libxo supports the '%m' directive, which formats the error message associated with the current value of "errno". It is the equivalent of "%s" with the argument strerror(errno).

     xo_emit("{:filename} cannot be opened: {:error/%m}", filename);
     xo_emit("{:filename} cannot be opened: {:error/%s}",
             filename, strerror(errno));
 	    

"%n" Is Not Supported

libxo does not support the '%n' directive. It's a bad idea and we just don't do it.

The Encoding Format (eformat)

The "eformat" string is the format string used when encoding the field for JSON and XML. If not provided, it defaults to the primary format with any minimum width removed. If the primary is not given, both default to "%s".

Content Strings

For padding and labels, the content string is considered the content, unless a format is given.

Argument Validation

Many compilers and tool chains support validation of printf-like arguments. When the format string fails to match the argument list, a warning is generated. This is a valuable feature and while the formatting strings for libxo differ considerably from printf, many of these checks can still provide build-time protection against bugs.

libxo provide variants of functions that provide this ability, if the "‑‑enable‑printflike" option is passed to the "configure" script. These functions use the "_p" suffix, like "xo_emit_p()", xo_emit_hp()", etc.

The following are features of libxo formatting strings that are incompatible with printf-like testing:

  • implicit formats, where "{:tag}" has an implicit "%s";
  • the "max" parameter for strings, where "{:tag/%4.10.6s}" means up to ten bytes of data can be inspected to fill a minimum of 4 columns and a maximum of 6;
  • percent signs in strings, where "{:filled}%" makes a single, trailing percent sign;
  • the "l" and "h" modifiers for strings, where "{:tag/%hs}" means locale-based string and "{:tag/%ls}" means a wide character string;
  • distinct encoding formats, where "{:tag/#%s/%s}" means the display styles (text and HTML) will use "#%s" where other styles use "%s";

If none of these features are in use by your code, then using the "_p" variants might be wise.

Function printf-like Equivalent
xo_emit_hv xo_emit_hvp
xo_emit_h xo_emit_hp
xo_emit xo_emit_p
xo_emit_warn_hcv xo_emit_warn_hcvp
xo_emit_warn_hc xo_emit_warn_hcp
xo_emit_warn_c xo_emit_warn_cp
xo_emit_warn xo_emit_warn_p
xo_emit_warnx_ xo_emit_warnx_p
xo_emit_err xo_emit_err_p
xo_emit_errx xo_emit_errx_p
xo_emit_errc xo_emit_errc_p

Retaining Parsed Format Information

libxo can retain the parsed internal information related to the given format string, allowing subsequent xo_emit calls, the retained information is used, avoiding repetitive parsing of the format string.

     SYNTAX:
       int xo_emit_f(xo_emit_flags_t flags, const char fmt, ...);
     EXAMPLE:
       xo_emit_f(XOEF_RETAIN, "{:some/%02d}{:thing/%-6s}{:fancy}\n",
                      some, thing, fancy);
 	    

To retain parsed format information, use the XOEF_RETAIN flag to the xo_emit_f() function. A complete set of xo_emit_f functions exist to match all the xo_emit function signatures (with handles, varadic argument, and printf-like flags):

Function Flags Equivalent
xo_emit_hv xo_emit_hvf
xo_emit_h xo_emit_hf
xo_emit xo_emit_f
xo_emit_hvp xo_emit_hvfp
xo_emit_hp xo_emit_hfp
xo_emit_p xo_emit_fp

The format string must be immutable across multiple calls to xo_emit_f(), since the library retains the string. Typically this is done by using static constant strings, such as string literals. If the string is not immutable, the XOEF_RETAIN flag must not be used.

The functions xo_retain_clear() and xo_retain_clear_all() release internal information on either a single format string or all format strings, respectively. Neither is required, but the library will retain this information until it is cleared or the process exits.

     const char *fmt = "{:name}  {:count/%d}\n";
     for (i = 0; i < 1000; i++) {
         xo_open_instance("item");
         xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]);
     }
     xo_retain_clear(fmt);
 	    

The retained information is kept as thread-specific data.

Example

In this example, the value for the number of items in stock is emitted:

         xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n",
                 instock);
 	    

This call will generate the following output:

   TEXT: 
        In stock: 144
   XML:
       <in-stock>144</in-stock>
   JSON:
       "in-stock": 144,
   HTML:
       <div class="line">
         <div class="padding">   </div>
         <div class="label">In stock</div>
         <div class="decoration">:</div>
         <div class="padding"> </div>
         <div class="data" data-tag="in-stock">144</div>
       </div>
 	    

Clearly HTML wins the verbosity award, and this output does not include XOF_XPATH or XOF_INFO data, which would expand the penultimate line to:

        <div class="data" data-tag="in-stock"
           data-xpath="/top/data/item/in-stock"
           data-type="number"
           data-help="Number of items in stock">144</div>
 	    

3.3 
Representing Hierarchy

For XML and JSON, individual fields appear inside hierarchies which provide context and meaning to the fields. Unfortunately, these encoding have a basic disconnect between how lists is similar objects are represented.

XML encodes lists as set of sequential elements:

     <user>phil</user>
     <user>pallavi</user>
     <user>sjg</user>
 	    

JSON encodes lists using a single name and square brackets:

     "user": [ "phil", "pallavi", "sjg" ]
 	    

This means libxo needs three distinct indications of hierarchy: one for containers of hierarchy appear only once for any specific parent, one for lists, and one for each item in a list.

Section Contents:

Containers

A "container" is an element of a hierarchy that appears only once under any specific parent. The container has no value, but serves to contain other nodes.

To open a container, call xo_open_container() or xo_open_container_h(). The former uses the default handle and the latter accepts a specific handle.

     int xo_open_container_h (xo_handle_t *xop, const char *name);
     int xo_open_container (const char *name);
 	    

To close a level, use the xo_close_container() or xo_close_container_h() functions:

     int xo_close_container_h (xo_handle_t *xop, const char *name);
     int xo_close_container (const char *name);
 	    

Each open call must have a matching close call. If the XOF_WARN flag is set and the name given does not match the name of the currently open container, a warning will be generated.

     Example:
 
         xo_open_container("top");
         xo_open_container("system");
         xo_emit("{:host-name/%s%s%s", hostname,
                 domainname ? "." : "", domainname ?: "");
         xo_close_container("system");
         xo_close_container("top");
 
     Sample Output:
       Text:
         my-host.example.org
       XML:
         <top>
           <system>
               <host-name>my-host.example.org</host-name>
           </system>
         </top>
       JSON:
         "top" : {
           "system" : {
               "host-name": "my-host.example.org"
           }
         }
       HTML:
         <div class="data"
              data-tag="host-name">my-host.example.org</div>
 	    

Lists and Instances

A list is set of one or more instances that appear under the same parent. The instances contain details about a specific object. One can think of instances as objects or records. A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list:

     xo_open_list("item");
 
     for (ip = list; ip->i_title; ip++) {
         xo_open_instance("item");
         xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
         xo_close_instance("item");
     }
 
     xo_close_list("item");
 	    

Getting the list and instance calls correct is critical to the proper generation of XML and JSON data.

DTRT Mode

Some users may find tracking the names of open containers, lists, and instances inconvenient. libxo offers a "Do The Right Thing" mode, where libxo will track the names of open containers, lists, and instances so the close function can be called without a name. To enable DTRT mode, turn on the XOF_DTRT flag prior to making any other libxo output.

     xo_set_flags(NULL, XOF_DTRT);
 	    

Each open and close function has a version with the suffix "_d", which will close the open container, list, or instance:

     xo_open_container("top");
     ...
     xo_close_container_d();
 	    

This also works for lists and instances:

     xo_open_list("item");
     for (...) {
         xo_open_instance("item");
         xo_emit(...);
         xo_close_instance_d();
     }
     xo_close_list_d();
 	    

Note that the XOF_WARN flag will also cause libxo to track open containers, lists, and instances. A warning is generated when the name given to the close function and the name recorded do not match.

Markers

Markers are used to protect and restore the state of open constructs. While a marker is open, no other open constructs can be closed. When a marker is closed, all constructs open since the marker was opened will be closed.

Markers use names which are not user-visible, allowing the caller to choose appropriate internal names.

In this example, the code whiffles through a list of fish, calling a function to emit details about each fish. The marker "fish‑guts" is used to ensure that any constructs opened by the function are closed properly.

     for (i = 0; fish[i]; i++) {
         xo_open_instance("fish");
         xo_open_marker("fish-guts");
         dump_fish_details(i);
         xo_close_marker("fish-guts");
     }
 	    

4_ 
Command-line Arguments

libxo uses command line options to trigger rendering behavior. The following options are recognised:

  • --libxo <options>
  • --libxo=<options>
  • --libxo:<brief‑options>

The following invocations are all identical in outcome:

   my-app --libxo warn,pretty arg1
   my-app --libxo=warn,pretty arg1
   my-app --libxo:WP arg1
 	    

Programs using libxo are expecting to call the xo_parse_args function to parse these arguments. See Section 5.4.1 for details.

Section Contents:

4.1 
Option keywords

Options is a comma-separated list of tokens that correspond to output styles, flags, or features:

Token Action
color Enable colors/effects for display styles (TEXT, HTML)
colors=xxxx Adjust color output values
dtrt Enable "Do The Right Thing" mode
flush Flush after every libxo function call
flush-line Flush after every line (line-buffered)
html Emit HTML output
indent=xx Set the indentation level
info Add info attributes (HTML)
json Emit JSON output
keys Emit the key attribute for keys (XML)
log-gettext Log (via stderr) each gettext(3) string lookup
log-syslog Log (via stderr) each syslog message (via xo_syslog)
no-humanize Ignore the {h:} modifier (TEXT, HTML)
no-locale Do not initialize the locale setting
no-retain Prevent retaining formatting information
no-top Do not emit a top set of braces (JSON)
not-first Pretend the 1st output item was not 1st (JSON)
pretty Emit pretty-printed output
retain Force retaining formatting information
text Emit TEXT output
underscores Replace XML-friendly "-"s with JSON friendly "_"s
units Add the 'units' (XML) or 'data-units (HTML) attribute
warn Emit warnings when libxo detects bad calls
warn-xml Emit warnings in XML
xml Emit XML output
xpath Add XPath expressions (HTML)

Most of these option are simple and direct, but some require additional details:

  • "colors" is described in Section 4.3.
  • "flush‑line" performs line buffering, even when the output is not directed to a TTY device.
  • "info" generates additional data for HTML, encoded in attributes using names that state with "data‑".
  • "keys" adds a "key" attribute for XML output to indicate that a leaf is an identifier for the list member.
  • "no‑humanize"avoids "humanizing" numeric output (see humanize_number(3) for details).
  • "no‑locale" instructs libxo to avoid translating output to the current locale.
  • "no‑retain" disables the ability of libxo to internally retain "compiled" information about formatting strings.
  • "underscores" can be used with JSON output to change XML-friendly names with dashes into JSON-friendly name with underscores.
  • "warn" allows libxo to emit warnings on stderr when application code make incorrect calls.
  • "warn‑xml" causes those warnings to be placed in XML inside the output.

4.2 
Brief Options

The brief options are simple single-letter aliases to the normal keywords, as detailed below:

Option Action
c Enable color/effects for TEXT/HTML
F Force line-buffered flushing
H Enable HTML output (XO_STYLE_HTML)
I Enable info output (XOF_INFO)
i<num> Indent by <number>
J Enable JSON output (XO_STYLE_JSON)
k Add keys to XPATH expressions in HTML
n Disable humanization (TEXT, HTML)
P Enable pretty-printed output (XOF_PRETTY)
T Enable text output (XO_STYLE_TEXT)
U Add units to HTML output
u Change "-"s to "_"s in element names (JSON)
W Enable warnings (XOF_WARN)
X Enable XML output (XO_STYLE_XML)
x Enable XPath data (XOF_XPATH)

4.3 
Color Mapping

The "colors" option takes a value that is a set of mappings from the pre-defined set of colors to new foreground and background colors. The value is a series of "fg/bg" values, separated by a "+". Each pair of "fg/bg" values gives the colors to which a basic color is mapped when used as a foreground or background color. The order is the mappings is:

  • black
  • red
  • green
  • yellow
  • blue
  • magenta
  • cyan
  • white

Pairs may be skipped, leaving them mapped as normal, as are missing pairs or single colors.

For example consider the following xo_emit call:

     xo_emit("{C:fg-red,bg-green}Merry XMas!!{C:}\n");
 	    

To turn all colored output to red-on-blue, use eight pairs of "red/blue" mappings separated by "+"s:

     --libxo colors=red/blue+red/blue+red/blue+red/blue+\
                    red/blue+red/blue+red/blue+red/blue
 	    

To turn the red-on-green text to magenta-on-cyan, give a "magenta" foreground value for red (the second mapping) and a "cyan" background to green (the third mapping):

     --libxo colors=+magenta+/cyan
 	    

Consider the common situation where blue output looks unreadable on a terminal session with a black background. To turn both "blue" foreground and background output to "yellow", give only the fifth mapping, skipping the first four mappings with bare "+"s:

     --libxo colors=++++yellow/yellow
 	    

5_ 
The libxo API

This section gives details about the functions in libxo, how to call them, and the actions they perform.

Section Contents:

5.1 
Handles

libxo uses "handles" to control its rendering functionality. The handle contains state and buffered data, as well as callback functions to process data.

Handles give an abstraction for libxo that encapsulates the state of a stream of output. Handles have the data type "xo_handle_t" and are opaque to the caller.

The library has a default handle that is automatically initialized. By default, this handle will send text style output (XO_STYLE_TEXT) to standard output. The xo_set_style and xo_set_flags functions can be used to change this behavior.

For the typical command that is generating output on standard output, there is no need to create an explicit handle, but they are available when needed, e.g., for daemons that generate multiple streams of output.

Many libxo functions take a handle as their first parameter; most that do not use the default handle. Any function taking a handle can be passed NULL to access the default handle. For the convenience of callers, the libxo library includes handle-less functions that implicitly use the default handle.

For example, the following are equivalent:

     xo_emit("test");
     xo_emit_h(NULL, "test");
 	    

Handles are created using xo_create() and destroy using xo_destroy().

Section Contents:

xo_create

A handle can be allocated using the xo_create() function:

     xo_handle_t *xo_create (unsigned style, unsigned flags);
 
   Example:
     xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN);
     ....
     xo_emit_h(xop, "testing\n");
 	    

See also Section 5.1.5.1 and Section 5.1.6.1.

xo_create_to_file

By default, libxo writes output to standard output. A convenience function is provided for situations when output should be written to a different file:

     xo_handle_t *xo_create_to_file (FILE *fp, unsigned style,
                                     unsigned flags);
 	    

Use the XOF_CLOSE_FP flag to trigger a call to fclose() for the FILE pointer when the handle is destroyed.

xo_set_writer

The xo_set_writer function allows custom 'write' functions which can tailor how libxo writes data. An opaque argument is recorded and passed back to the write function, allowing the function to acquire context information. The 'close' function can release this opaque data and any other resources as needed. The flush function can flush buffered data associated with the opaque object.

     void xo_set_writer (xo_handle_t *xop, void *opaque,
                         xo_write_func_t write_func,
                         xo_close_func_t close_func);
                         xo_flush_func_t flush_func);
 	    

xo_set_style

To set the style, use the xo_set_style() function:

     void xo_set_style(xo_handle_t *xop, unsigned style);
 	    

To use the default handle, pass a NULL handle:

     xo_set_style(NULL, XO_STYLE_XML);
 	    

xo_get_style

To find the current style, use the xo_get_style() function:

     xo_style_t xo_get_style(xo_handle_t *xop);
 	    

To use the default handle, pass a NULL handle:

     style = xo_get_style(NULL);
 	    

Section Contents:

Output Styles (XO_STYLE_*)

The libxo functions accept a set of output styles:

Flag Description
XO_STYLE_TEXT Traditional text output
XO_STYLE_XML XML encoded data
XO_STYLE_JSON JSON encoded data
XO_STYLE_HTML HTML encoded data

xo_set_style_name

The xo_set_style_name() can be used to set the style based on a name encoded as a string:

     int xo_set_style_name (xo_handle_t *xop, const char *style);
 	    

The name can be any of the styles: "text", "xml", "json", or "html".

     EXAMPLE:
         xo_set_style_name(NULL, "html");
 	    

xo_set_flags

To set the flags, use the xo_set_flags() function:

     void xo_set_flags(xo_handle_t *xop, unsigned flags);
 	    

To use the default handle, pass a NULL handle:

     xo_set_style(NULL, XO_STYLE_XML);
 	    

Section Contents:

Flags (XOF_*)

The set of valid flags include:

Flag Description
XOF_CLOSE_FP Close file pointer on xo_destroy()
XOF_COLOR Enable color and effects in output
XOF_COLOR_ALLOWED Allow color/effect for terminal output
XOF_DTRT Enable "do the right thing" mode
XOF_INFO Display info data attributes (HTML)
XOF_KEYS Emit the key attribute (XML)
XOF_NO_ENV Do not use the LIBXO_OPTIONS env var
XOF_NO_HUMANIZE Display humanization (TEXT, HTML)
XOF_PRETTY Make 'pretty printed' output
XOF_UNDERSCORES Replaces hyphens with underscores
XOF_UNITS Display units (XML, HMTL)
XOF_WARN Generate warnings for broken calls
XOF_WARN_XML Generate warnings in XML on stdout
XOF_XPATH Emit XPath expressions (HTML)
XOF_COLUMNS Force xo_emit to return columns used
XOF_FLUSH Flush output after each xo_emit call

The XOF_CLOSE_FP flag will trigger the call of the close_func (provided via xo_set_writer()) when the handle is destroyed.

The XOF_COLOR flag enables color and effects in output regardless of output device, while the XOF_COLOR_ALLOWED flag allows color and effects only if the output device is a terminal.

The XOF_PRETTY flag requests 'pretty printing', which will trigger the addition of indentation and newlines to enhance the readability of XML, JSON, and HTML output. Text output is not affected.

The XOF_WARN flag requests that warnings will trigger diagnostic output (on standard error) when the library notices errors during operations, or with arguments to functions. Without warnings enabled, such conditions are ignored.

Warnings allow developers to debug their interaction with libxo. The function "xo_failure" can used as a breakpoint for a debugger, regardless of whether warnings are enabled.

If the style is XO_STYLE_HTML, the following additional flags can be used:

Flag Description
XOF_XPATH Emit "data-xpath" attributes
XOF_INFO Emit additional info fields

The XOF_XPATH flag enables the emission of XPath expressions detailing the hierarchy of XML elements used to encode the data field, if the XPATH style of output were requested.

The XOF_INFO flag encodes additional informational fields for HTML output. See Section 5.4.4 for details.

If the style is XO_STYLE_XML, the following additional flags can be used:

Flag Description
XOF_KEYS Flag 'key' fields for xml

The XOF_KEYS flag adds 'key' attribute to the XML encoding for field definitions that use the 'k' modifier. The key attribute has the value "key":

     xo_emit("{k:name}", item);
 
   XML:
       <name key="key">truck</name>
 	    

xo_clear_flags

The xo_clear_flags() function turns off the given flags in a specific handle.

     void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags);
 	    

xo_set_options

The xo_set_options() function accepts a comma-separated list of styles and flags and enables them for a specific handle.

     int xo_set_options (xo_handle_t *xop, const char *input);
 	    

The options are identical to those listed in Section 4.

xo_destroy

The xo_destroy function releases a handle and any resources it is using. Calling xo_destroy with a NULL handle will release any resources associated with the default handle.

     void xo_destroy(xo_handle_t *xop);
 	    

5.2 
Emitting Content (xo_emit)

The following functions are used to emit output:

     int xo_emit (const char *fmt, ...);
     int xo_emit_h (xo_handle_t *xop, const char *fmt, ...);
     int xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap);
 	    

The "fmt" argument is a string containing field descriptors as specified in Section 3.2. The use of a handle is optional and NULL can be passed to access the internal 'default' handle. See Section 5.1.

The remaining arguments to xo_emit() and xo_emit_h() are a set of arguments corresponding to the fields in the format string. Care must be taken to ensure the argument types match the fields in the format string, since an inappropriate cast can ruin your day. The vap argument to xo_emit_hv() points to a variable argument list that can be used to retrieve arguments via va_arg().

Section Contents:

Single Field Emitting Functions (xo_emit_field)

The following functions can also make output, but only make a single field at a time:

     int xo_emit_field_hv (xo_handle_t *xop, const char *rolmod,
                   const char *contents, const char *fmt, 
                   const char *efmt, va_list vap);
 
     int xo_emit_field_h (xo_handle_t *xop, const char *rolmod, 
                  const char *contents, const char *fmt,
                  const char *efmt, ...);
 
     int xo_emit_field (const char *rolmod, const char *contents,
                  const char *fmt, const char *efmt, ...);
 	    

These functions are intended to avoid the scenario where one would otherwise need to compose a format descriptors using snprintf(). The individual parts of the format descriptor are passed in distinctly.

     xo_emit("T", "Host name is ", NULL, NULL);
     xo_emit("V", "host-name", NULL, NULL, host-name);
 	    

Attributes (xo_attr)

The xo_attr() function emits attributes for the XML output style.

     int xo_attr (const char *name, const char *fmt, ...);
     int xo_attr_h (xo_handle_t *xop, const char *name, 
                    const char *fmt, ...);
     int xo_attr_hv (xo_handle_t *xop, const char *name, 
                    const char *fmt, va_list vap);
 	    

The name parameter give the name of the attribute to be encoded. The fmt parameter gives a printf-style format string used to format the value of the attribute using any remaining arguments, or the vap parameter passed to xo_attr_hv().

     EXAMPLE:
       xo_attr("seconds", "%ld", (unsigned long) login_time);
       struct tm *tmp = localtime(login_time);
       strftime(buf, sizeof(buf), "%R", tmp);
       xo_emit("Logged in at {:login-time}\n", buf);
     XML:
         <login-time seconds="1408336270">00:14</login-time>
 	    

xo_attr is placed on the next container, instance, leaf, or leaf list that is emitted.

Since attributes are only emitted in XML, their use should be limited to meta-data and additional or redundant representations of data already emitted in other form.

Flushing Output (xo_flush)

libxo buffers data, both for performance and consistency, but also to allow some advanced features to work properly. At various times, the caller may wish to flush any data buffered within the library. The xo_flush() call is used for this:

     void xo_flush (void);
     void xo_flush_h (xo_handle_t *xop);
 	    

Calling xo_flush also triggers the flush function associated with the handle. For the default handle, this is equivalent to "fflush(stdio);".

Finishing Output (xo_finish)

When the program is ready to exit or close a handle, a call to xo_finish() is required. This flushes any buffered data, closes open libxo constructs, and completes any pending operations.

     int xo_finish (void);
     int xo_finish_h (xo_handle_t *xop);
     void xo_finish_atexit (void);
 	    

Calling this function is vital to the proper operation of libxo, especially for the non-TEXT output styles.

xo_finish_atexit is suitable for use with atexit(3).

5.3 
Emitting Hierarchy

libxo represents to types of hierarchy: containers and lists. A container appears once under a given parent where a list contains instances that can appear multiple times. A container is used to hold related fields and to give the data organization and scope.

To create a container, use the xo_open_container and xo_close_container functions:

     int xo_open_container (const char *name);
     int xo_open_container_h (xo_handle_t *xop, const char *name);
     int xo_open_container_hd (xo_handle_t *xop, const char *name);
     int xo_open_container_d (const char *name);
 
     int xo_close_container (const char *name);
     int xo_close_container_h (xo_handle_t *xop, const char *name);
     int xo_close_container_hd (xo_handle_t *xop);
     int xo_close_container_d (void);
 	    

The name parameter gives the name of the container, encoded in UTF-8. Since ASCII is a proper subset of UTF-8, traditional C strings can be used directly.

The close functions with the "_d" suffix are used in "Do The Right Thing" mode, where the name of the open containers, lists, and instances are maintained internally by libxo to allow the caller to avoid keeping track of the open container name.

Use the XOF_WARN flag to generate a warning if the name given on the close does not match the current open container.

For TEXT and HTML output, containers are not rendered into output text, though for HTML they are used when the XOF_XPATH flag is set.

     EXAMPLE:
        xo_open_container("system");
        xo_emit("The host name is {:host-name}\n", hn);
        xo_close_container("system");
     XML:
        <system><host-name>foo</host-name></system>
 	    

Section Contents:

Lists and Instances

Lists are sequences of instances of homogeneous data objects. Two distinct levels of calls are needed to represent them in our output styles. Calls must be made to open and close a list, and for each instance of data in that list, calls must be make to open and close that instance.

The name given to all calls must be identical, and it is strongly suggested that the name be singular, not plural, as a matter of style and usage expectations.

     EXAMPLE:
         xo_open_list("user");
         for (i = 0; i < num_users; i++) {
             xo_open_instance("user");
             xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n",
                     pw[i].pw_name, pw[i].pw_uid,
                     pw[i].pw_gid, pw[i].pw_dir);
             xo_close_instance("user");
         }
         xo_close_list("user");
     TEXT:
         phil:1001:1001:/home/phil
         pallavi:1002:1002:/home/pallavi
     XML:
         <user>
             <name>phil</name>
             <uid>1001</uid>
             <gid>1001</gid>
             <home>/home/phil</home>
         </user>
         <user>
             <name>pallavi</name>
             <uid>1002</uid>
             <gid>1002</gid>
             <home>/home/pallavi</home>
         </user>
     JSON:
         user: [
             {
                 "name": "phil",
                 "uid": 1001,
                 "gid": 1001,
                 "home": "/home/phil",
             },
             {
                 "name": "pallavi",
                 "uid": 1002,
                 "gid": 1002,
                 "home": "/home/pallavi",
             }
         ]
 	    

5.4 
Support Functions

Section Contents:

Parsing Command-line Arguments (xo_parse_args)

The xo_parse_args() function is used to process a program's arguments. libxo-specific options are processed and removed from the argument list so the calling application does not need to process them. If successful, a new value for argc is returned. On failure, a message it emitted and -1 is returned.

     argc = xo_parse_args(argc, argv);
     if (argc < 0)
         exit(EXIT_FAILURE);
 	    

Following the call to xo_parse_args, the application can process the remaining arguments in a normal manner. See Section 4 for a description of valid arguments.

xo_set_program

The xo_set_program function sets name of the program as reported by functions like xo_failure, xo_warn, xo_err, etc. The program name is initialized by xo_parse_args, but subsequent calls to xo_set_program can override this value.

     xo_set_program(argv[0]);
 	    

Note that the value is not copied, so the memory passed to xo_set_program (and xo_parse_args) must be maintained by the caller.

xo_set_version

The xo_set_version function records a version number to be emitted as part of the data for encoding styles (XML and JSON). This version number is suitable for tracking changes in the content, allowing a user of the data to discern which version of the data model is in use.

      void xo_set_version (const char *version);
      void xo_set_version_h (xo_handle_t *xop, const char *version);
 	    

Field Information (xo_info_t)

HTML data can include additional information in attributes that begin with "data‑". To enable this, three things must occur:

First the application must build an array of xo_info_t structures, one per tag. The array must be sorted by name, since libxo uses a binary search to find the entry that matches names from format instructions.

Second, the application must inform libxo about this information using the xo_set_info() call:

     typedef struct xo_info_s {
         const char *xi_name;    /* Name of the element */
         const char *xi_type;    /* Type of field */
         const char *xi_help;    /* Description of field */
     } xo_info_t;
 
     void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count);
 	    

Like other libxo calls, passing NULL for the handle tells libxo to use the default handle.

If the count is -1, libxo will count the elements of infop, but there must be an empty element at the end. More typically, the number is known to the application:

     xo_info_t info[] = {
         { "in-stock", "number", "Number of items in stock" },
         { "name", "string", "Name of the item" },
         { "on-order", "number", "Number of items on order" },
         { "sku", "string", "Stock Keeping Unit" },
         { "sold", "number", "Number of items sold" },
     };
     int info_count = (sizeof(info) / sizeof(info[0]));
     ...
     xo_set_info(NULL, info, info_count);
 	    

Third, the emission of info must be triggered with the XOF_INFO flag using either the xo_set_flags() function or the "‑‑libxo=info" command line argument.

The type and help values, if present, are emitted as the "data‑type" and "data‑help" attributes:

   <div class="data" data-tag="sku" data-type="string" 
        data-help="Stock Keeping Unit">GRO-000-533</div>
 	    

Memory Allocation

The xo_set_allocator function allows libxo to be used in environments where the standard realloc() and free() functions are not available.

     void xo_set_allocator (xo_realloc_func_t realloc_func,
                            xo_free_func_t free_func);
 	    

realloc_func should expect the same arguments as realloc(3) and return a pointer to memory following the same convention. free_func will receive the same argument as free(3) and should release it, as appropriate for the environment.

By default, the standard realloc() and free() functions are used.

LIBXO_OPTIONS

The environment variable "LIBXO_OPTIONS" can be set to a subset of libxo options, including:

  • color
  • flush
  • flush-line
  • no-color
  • no-humanize
  • no-locale
  • no-retain
  • pretty
  • retain
  • underscores
  • warn

For example, warnings can be enabled by:

     % env LIBXO_OPTIONS=warn my-app
 	    

Since environment variables are inherited, child processes will have the same options, which may be undesirable, making the use of the "‑‑libxo" option is preferable in most situations.

Errors, Warnings, and Messages

Many programs make use of the standard library functions err() and warn() to generate errors and warnings for the user. libxo wants to pass that information via the current output style, and provides compatible functions to allow this:

     void xo_warn (const char *fmt, ...);
     void xo_warnx (const char *fmt, ...);
     void xo_warn_c (int code, const char *fmt, ...);
     void xo_warn_hc (xo_handle_t *xop, int code,
                      const char *fmt, ...);
     void xo_err (int eval, const char *fmt, ...);
     void xo_errc (int eval, int code, const char *fmt, ...);
     void xo_errx (int eval, const char *fmt, ...);
     void xo_message (const char *fmt, ...);
     void xo_message_c (int code, const char *fmt, ...);
     void xo_message_hc (xo_handle_t *xop, int code,
                         const char *fmt, ...);
     void xo_message_hcv (xo_handle_t *xop, int code, 
                          const char *fmt, va_list vap);
 	    

These functions display the program name, a colon, a formatted message based on the arguments, and then optionally a colon and an error message associated with either "errno" or the "code" parameter.

     EXAMPLE:
         if (open(filename, O_RDONLY) < 0)
             xo_err(1, "cannot open file '%s'", filename);
 	    

xo_error

The xo_error function can be used for generic errors that should be reported over the handle, rather than to stderr. The xo_error function behaves like xo_err for TEXT and HTML output styles, but puts the error into XML or JSON elements:

     EXAMPLE::
         xo_error("Does not %s", "compute");
     XML::
         <error><message>Does not compute</message></error>
     JSON::
         "error": { "message": "Does not compute" }
 	    

xo_no_setlocale

libxo automatically initializes the locale based on setting of the environment variables LC_CTYPE, LANG, and LC_ALL. The first of this list of variables is used and if none of the variables, the locale defaults to "UTF‑8". The caller may wish to avoid this behavior, and can do so by calling the xo_no_setlocale() function.

     void xo_no_setlocale (void);
 	    

5.5 
Emitting syslog Messages

syslog is the system logging facility used throughout the unix world. Messages are sent from commands, applications, and daemons to a hierarchy of servers, where they are filtered, saved, and forwarded based on configuration behaviors.

syslog is an older protocol, originally documented only in source code. By the time RFC 3164 published, variation and mutation left the leading "<pri>" string as only common content. RFC 5424 defines a new version (version 1) of syslog and introduces structured data into the messages. Structured data is a set of name/value pairs transmitted distinctly alongside the traditional text message, allowing filtering on precise values instead of regular expressions.

These name/value pairs are scoped by a two-part identifier; an enterprise identifier names the party responsible for the message catalog and a name identifying that message. Enterprise IDs are defined by IANA, the Internet Assigned Numbers Authority:

https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers

Use the Section 5.5.3.5() function to set the Enterprise ID, as needed.

The message name should follow the conventions in Section 10.1.3, as should the fields within the message.

     /* Both of these calls are optional */
     xo_set_syslog_enterprise_id(32473);
     xo_open_log("my-program", 0, LOG_DAEMON);
 
     /* Generate a syslog message */
     xo_syslog(LOG_ERR, "upload-failed",
               "error <%d> uploading file '{:filename}' "
               "as '{:target/%s:%s}'",
               code, filename, protocol, remote);
 
     xo_syslog(LOG_INFO, "poofd-invalid-state",
               "state {:current/%u} is invalid {:connection/%u}",
               state, conn);
 	    

The developer should be aware that the message name may be used in the future to allow access to further information, including documentation. Care should be taken to choose quality, descriptive names.

Section Contents:

Priority, Facility, and Flags

The xo_syslog, xo_vsyslog, and xo_open_log functions accept a set of flags which provide the priority of the message, the source facility, and some additional features. These values are OR'd together to create a single integer argument:

     xo_syslog(LOG_ERR | LOG_AUTH, "login-failed",
              "Login failed; user '{:user}' from host '{:address}'",
              user, addr);
 	    

These values are defined in <syslog.h>.

The priority value indicates the importance and potential impact of each message.

Priority Description
LOG_EMERG A panic condition, normally broadcast to all users
LOG_ALERT A condition that should be corrected immediately
LOG_CRIT Critical conditions
LOG_ERR Generic errors
LOG_WARNING Warning messages
LOG_NOTICE Non-error conditions that might need special handling
LOG_INFO Informational messages
LOG_DEBUG Developer-oriented messages

The facility value indicates the source of message, in fairly generic terms.

Facility Description
LOG_AUTH The authorization system (e.g. login(1))
LOG_AUTHPRIV As LOG_AUTH, but logged to a privileged file
LOG_CRON The cron daemon: cron(8)
LOG_DAEMON System daemons, not otherwise explicitly listed
LOG_FTP The file transfer protocol daemons
LOG_KERN Messages generated by the kernel
LOG_LPR The line printer spooling system
LOG_MAIL The mail system
LOG_NEWS The network news system
LOG_SECURITY Security subsystems, such as ipfw(4)
LOG_SYSLOG Messages generated internally by syslogd(8)
LOG_USER Messages generated by user processes (default)
LOG_UUCP The uucp system
LOG_LOCAL0..7 Reserved for local use

In addition to the values listed above, xo_open_log accepts a set of addition flags requesting specific behaviors.

Flag Description
LOG_CONS If syslogd fails, attempt to write to /dev/console
LOG_NDELAY Open the connection to syslogd(8) immediately
LOG_PERROR Write the message also to standard error output
LOG_PID Log the process id with each message

xo_syslog

Use the xo_syslog function to generate syslog messages by calling it with a log priority and facility, a message name, a format string, and a set of arguments. The priority/facility argument are discussed above, as is the message name.

The format string follows the same conventions as xo_emit's format string, with each field being rendered as an SD-PARAM pair.

     xo_syslog(LOG_ERR, "poofd-missing-file",
               "'{:filename}' not found: {:error/%m}", filename);
 
     ... [poofd-missing-file@32473 filename="/etc/poofd.conf"
           error="Permission denied"] '/etc/poofd.conf' not
           found: Permission denied
 	    

Support functions

Section Contents:

xo_vsyslog

xo_vsyslog is identical in function to xo_syslog, but takes the set of arguments using a va_list.

     void my_log (const char *name, const char *fmt, ...)
     {
         va_list vap;
         va_start(vap, fmt);
         xo_vsyslog(LOG_ERR, name, fmt, vap);
         va_end(vap);
     }
 	    

xo_open_log

xo_open_log functions similar to openlog(3), allowing customization of the program name, the log facility number, and the additional option flags described in Section 5.5.1.

     void
     xo_open_log (const char *ident, int logopt, int facility);
 	    

xo_close_log

xo_close_log functions similar to closelog(3), closing the log file and releasing any associated resources.

     void
     xo_close_log (void);
 	    

xo_set_logmask

xo_set_logmask function similar to setlogmask(3), restricting the set of generated log event to those whose associated bit is set in maskpri. Use LOG_MASK(pri) to find the appropriate bit, or LOG_UPTO(toppri) to create a mask for all priorities up to and including toppri.

     int
     xo_set_logmask (int maskpri);
 
   Example:
     setlogmask(LOG_UPTO(LOG_WARN));
 	    

xo_set_syslog_enterprise_id

Use the xo_set_syslog_enterprise_id to supply a platform- or application-specific enterprise id. This value is used in any future syslog messages.

Ideally, the operating system should supply a default value via the "kern.syslog.enterprise_id" sysctl value. Lacking that, the application should provide a suitable value.

     void
     xo_set_syslog_enterprise_id (unsigned short eid);
 	    

Enterprise IDs are administered by IANA, the Internet Assigned Number Authority. The complete list is EIDs on their web site:

https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers

New EIDs can be requested from IANA using the following page:

http://pen.iana.org/pen/PenApplication.page

Each software development organization that defines a set of syslog messages should register their own EID and use that value in their software to ensure that messages can be uniquely identified by the combination of EID + message name.

5.6 
Creating Custom Encoders

The number of encoding schemes in current use is staggering, with new and distinct schemes appearing daily. While libxo provide XML, JSON, HMTL, and text natively, there are requirements for other encodings.

Rather than bake support for all possible encoders into libxo, the API allows them to be defined externally. libxo can then interfaces with these encoding modules using a simplistic API. libxo processes all functions calls, handles state transitions, performs all formatting, and then passes the results as operations to a customized encoding function, which implements specific encoding logic as required. This means your encoder doesn't need to detect errors with unbalanced open/close operations but can rely on libxo to pass correct data.

By making a simple API, libxo internals are not exposed, insulating the encoder and the library from future or internal changes.

The three elements of the API are:

  • loading
  • initialization
  • operations

The following sections provide details about these topics.

libxo source contain an encoder for Concise Binary Object Representation, aka CBOR (RFC 7049) which can be used as used as an example for the API.

Section Contents:

Loading Encoders

Encoders can be registered statically or discovered dynamically. Applications can choose to call the xo_encoder_register() function to explicitly register encoders, but more typically they are built as shared libraries, placed in the libxo/extensions directory, and loaded based on name. libxo looks for a file with the name of the encoder and an extension of ".enc". This can be a file or a symlink to the shared library file that supports the encoder.

     % ls -1 lib/libxo/extensions/*.enc
     lib/libxo/extensions/cbor.enc
     lib/libxo/extensions/test.enc
 	    

Encoder Initialization

Each encoder must export a symbol used to access the library, which must have the following signature:

     int xo_encoder_library_init (XO_ENCODER_INIT_ARGS);
 	    

XO_ENCODER_INIT_ARGS is a macro defined in xo_encoder.h that defines an argument called "arg", a pointer of the type xo_encoder_init_args_t. This structure contains two fields:

  • xei_version is the version number of the API as implemented within libxo. This version is currently as 1 using XO_ENCODER_VERSION. This number can be checked to ensure compatibility. The working assumption is that all versions should be backward compatible, but each side may need to accurately know the version supported by the other side. xo_encoder_library_init can optionally check this value, and must then set it to the version number used by the encoder, allowing libxo to detect version differences and react accordingly. For example, if version 2 adds new operations, then libxo will know that an encoding library that set xei_version to 1 cannot be expected to handle those new operations.
  • xei_handler must be set to a pointer to a function of type xo_encoder_func_t, as defined in xo_encoder.h. This function takes a set of parameters: -- xop is a pointer to the opaque xo_handle_t structure -- op is an integer representing the current operation -- name is a string whose meaning differs by operation -- value is a string whose meaning differs by operation -- private is an opaque structure provided by the encoder

Additional arguments may be added in the future, so handler functions should use the XO_ENCODER_HANDLER_ARGS macro. An appropriate "extern" declaration is provided to help catch errors.

Once the encoder initialization function has completed processing, it should return zero to indicate that no error has occurred. A non-zero return code will cause the handle initialization to fail.

Operations

The encoder API defines a set of operations representing the processing model of libxo. Content is formatted within libxo, and callbacks are made to the encoder's handler function when data is ready to be processed.

Operation Meaning (Base function)
XO_OP_CREATE Called when the handle is created
XO_OP_OPEN_CONTAINER Container opened (xo_open_container)
XO_OP_CLOSE_CONTAINER Container closed (xo_close_container)
XO_OP_OPEN_LIST List opened (xo_open_list)
XO_OP_CLOSE_LIST List closed (xo_close_list)
XO_OP_OPEN_LEAF_LIST Leaf list opened (xo_open_leaf_list)
XO_OP_CLOSE_LEAF_LIST Leaf list closed (xo_close_leaf_list)
XO_OP_OPEN_INSTANCE Instance opened (xo_open_instance)
XO_OP_CLOSE_INSTANCE Instance closed (xo_close_instance)
XO_OP_STRING Field with Quoted UTF-8 string
XO_OP_CONTENT Field with content
XO_OP_FINISH Finish any pending output
XO_OP_FLUSH Flush any buffered output
XO_OP_DESTROY Clean up resources
XO_OP_ATTRIBUTE An attribute name/value pair
XO_OP_VERSION A version string

For all the open and close operations, the name parameter holds the name of the construct. For string, content, and attribute operations, the name parameter is the name of the field and the value parameter is the value. "string" are differentiated from "content" to allow differing treatment of true, false, null, and numbers from real strings, though content values are formatted as strings before the handler is called. For version operations, the value parameter contains the version.

All strings are encoded in UTF-8.


6_ 
The "xo" Utility

The "xo" utility allows command line access to the functionality of the libxo library. Using "xo", shell scripts can emit XML, JSON, and HTML using the same commands that emit text output.

The style of output can be selected using a specific option: "‑X" for XML, "‑J" for JSON, "‑H" for HTML, or "‑T" for TEXT, which is the default. The "--style <style>" option can also be used. The standard set of "‑‑libxo" options are available (see Section 4), as well as the LIBXO_OPTIONS environment variable (see Section 5.4.6).

The "xo" utility accepts a format string suitable for xo_emit() and a set of zero or more arguments used to supply data for that string.

     xo "The {k:name} weighs {:weight/%d} pounds.\n" fish 6
 
   TEXT:
     The fish weighs 6 pounds.
   XML:
     <name>fish</name>
     <weight>6</weight>
   JSON:
     "name": "fish",
     "weight": 6
   HTML:
     <div class="line">
       <div class="text">The </div>
       <div class="data" data-tag="name">fish</div>
       <div class="text"> weighs </div>
       <div class="data" data-tag="weight">6</div>
       <div class="text"> pounds.</div>
     </div>
 	    

The "--wrap <path>" option can be used to wrap emitted content in a specific hierarchy. The path is a set of hierarchical names separated by the '/' character.

     xo --wrap top/a/b/c '{:tag}' value
 
   XML:
     <top>
       <a>
         <b>
           <c>
             <tag>value</tag>
           </c>
         </b>
       </a>
     </top>
   JSON:
     "top": {
       "a": {
         "b": {
           "c": {
             "tag": "value"
           }
         }
       }
     }
 	    

The "--open <path>" and "--close <path>" can be used to emit hierarchical information without the matching close and open tag. This allows a shell script to emit open tags, data, and then close tags. The "‑‑depth" option may be used to set the depth for indentation. The "‑‑leading‑xpath" may be used to prepend data to the XPath values used for HTML output style.

     #!/bin/sh
     xo --open top/data
     xo --depth 2 '{tag}' value
     xo --close top/data
   XML:
     <top>
       <data>
         <tag>value</tag>
       </data>
     </top>
   JSON:
     "top": {
       "data": {
         "tag": "value"
       }
     }
 	    

Section Contents:

6.1 
Command Line Options

Usage: xo [options] format [fields]

   --close <path>        Close tags for the given path
   --depth <num>         Set the depth for pretty printing
   --help                Display this help text
   --html OR -H          Generate HTML output
   --json OR -J          Generate JSON output
   --leading-xpath <path> Add a prefix to generated XPaths (HTML)
   --open <path>         Open tags for the given path
   --pretty OR -p        Make 'pretty' output (add indent, newlines)
   --style <style>       Generate given style (xml, json, text, html)
   --text OR -T          Generate text output (the default style)
   --version             Display version information
   --warn OR -W          Display warnings in text on stderr
   --warn-xml            Display warnings in xml on stdout
   --wrap <path>         Wrap output in a set of containers
   --xml OR -X           Generate XML output
   --xpath               Add XPath data to HTML output);
 	    

6.2 
Example

   % xo 'The {:product} is {:status}\n' stereo "in route"
   The stereo is in route
   % ./xo/xo -p -X 'The {:product} is {:status}\n' stereo "in route"
   <product>stereo</product>
   <status>in route</status>
 	    

7_ 
xolint

xolint is a tool for reporting common mistakes in format strings in source code that invokes xo_emit(). It allows these errors to be diagnosed at build time, rather than waiting until runtime.

xolint takes the one or more C files as arguments, and reports and errors, warning, or informational messages as needed.

Option Meaning
-c Invoke 'cpp' against the input file
-C <flags> Flags that are passed to 'cpp
-d Enable debug output
-D Generate documentation for all xolint messages
-I Generate info table code
-p Print the offending lines after the message
-V Print vocabulary of all field names
-X Extract samples from xolint, suitable for testing

The output message will contain the source filename and line number, the class of the message, the message, and, if -p is given, the line that contains the error:

     % xolint.pl -t xolint.c
     xolint.c: 16: error: anchor format should be "%d"
     16         xo_emit("{[:/%s}");
 	    

The "‑I" option will generate a table of xo_info_t structures ,

The "‑V" option does not report errors, but prints a complete list of all field names, sorted alphabetically. The output can help spot inconsistencies and spelling errors.


8_ 
xohtml

xohtml is a tool for turning the output of libxo-enabled commands into html files suitable for display in modern HTML web browsers. It can be used to test and debug HTML output, as well as to make the user ache to escape the world of 70s terminal devices.

xohtml is given a command, either on the command line or via the "‑c" option. If not command is given, standard input is used. The command's output is wrapped in HTML tags, with references to supporting CSS and Javascript files, and written to standard output or the file given in the "‑f" option. The "‑b" option can be used to provide an alternative base path for the support files.

Option Meaning
-b <base> Base path for finding css/javascript files
-c <command> Command to execute
-f <file> Output file name

The "‑c" option takes a full command with arguments, including any libxo options needed to generate html ("‑‑libxo=html"). This value must be quoted if it consists of multiple tokens.


9_ 
xopo

The "xopo" utility filters ".pot" files generated by the "xgettext" utility to remove formatting information suitable for use with the "{G:}" modifier. This means that when the developer changes the formatting portion of the field definitions, or the fields modifiers, the string passed to gettext(3) is unchanged, avoiding the expense of updating any existing translation files (".po" files).

The syntax for the xopo command is one of two forms; it can be used as a filter for processing a .po or .pot file, rewriting the "msgid" strings with a simplified message string. In this mode, the input is either standard input or a file given by the "‑f" option, and the output is either standard output or a file given by the "‑o" option.

In the second mode, a simple message given using the "‑s" option on the command, and the simplified version of that message is printed on stdout.

Option Meaning
-o <file> Output file name
-f <file> Use the given .po file as input
-s <text> Simplify a format string
     EXAMPLE:
         % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
         There are {:count} {:event} events\n
 
         % xgettext --default-domain=foo --no-wrap \
             --add-comments --keyword=xo_emit --keyword=xo_emit_h \
             --keyword=xo_emit_warn -C -E -n --foreign-user \
             -o foo.pot.raw foo.c
         % xopo -f foo.pot.raw -o foo.pot
 	    

Use of the "‑‑no‑wrap" option for xgettext is required to ensure that incoming msgid strings are not wrapped across multiple lines.


10_ 
FAQs

This section contains the set of questions that users typically ask, along with answers that might be helpful.

Section Contents:

Section Contents:

10.1 
General

Section Contents:

Can you share the history of libxo?

In 2001, we added an XML API to the JUNOS operating system, which is built on top of FreeBSD. Eventually this API became standardized as the NETCONF API (RFC 6241). As part of this effort, we modified many FreeBSD utilities to emit XML, typically via a "‑X" switch. The results were mixed. The cost of maintaining this code, updating it, and carrying it were non-trivial, and contributed to our expense (and the associated delay) with upgrading the version of FreeBSD on which each release of JUNOS is based.

A recent (2014) effort within JUNOS aims at removing our modifications to the underlying FreeBSD code as a means of reducing the expense and delay in tracking HEAD. JUNOS is structured to have system components generate XML that is rendered by the CLI (think: login shell) into human-readable text. This allows the API to use the same plumbing as the CLI, and ensures that all components emit XML, and that it is emitted with knowledge of the consumer of that XML, yielding an API that have no incremental cost or feature delay.

libxo is an effort to mix the best aspects of the JUNOS strategy into FreeBSD in a seemless way, allowing commands to make printf-like output calls with a single code path.

Did the complex semantics of format strings evolve over time?

The history is both long and short: libxo's functionality is based on what JUNOS does in a data modeling language called ODL (output definition language). In JUNOS, all subcomponents generate XML, which is feed to the CLI, where data from the ODL files tell is how to render that XML into text. ODL might had a set of tags like:

      tag docsis-state {
          help "State of the DOCSIS interface";
          type string;
      }
 
      tag docsis-mode {
          help "DOCSIS mode (2.0/3.0) of the DOCSIS interface";
          type string;
      }
 
      tag docsis-upstream-speed {
          help "Operational upstream speed of the interface";
          type string;
      }
 
      tag downstream-scanning {
          help "Result of scanning in downstream direction";
          type string;
      }
 
      tag ranging {
          help "Result of ranging action";
          type string;
      }
 
      tag signal-to-noise-ratio {
          help "Signal to noise ratio for all channels";
          type string;
      }
 
      tag power {
          help "Operational power of the signal on all channels";
          type string;
      }
 
      format docsis-status-format {
          picture "
    State   : @, Mode: @, Upstream speed: @
    Downstream scanning: @, Ranging: @
    Signal to noise ratio: @
    Power: @
 ";
          line {
              field docsis-state;
              field docsis-mode;
              field docsis-upstream-speed;
              field downstream-scanning;
              field ranging;
              field signal-to-noise-ratio;
              field power;
          }
      }
 	    

These tag definitions are compiled into field definitions that are triggered when matching XML elements are seen. ODL also supports other means of defining output.

The roles and modifiers describe these details.

In moving these ideas to bsd, two things had to happen: the formatting had to happen at the source since BSD won't have a JUNOS-like CLI to do the rendering, and we can't depend on external data models like ODL, which was seen as too hard a sell to the BSD community.

The results were that the xo_emit strings are used to encode the roles, modifiers, names, and formats. They are dense and a bit cryptic, but not so unlike printf format strings that developers will be lost.

libxo is a new implementation of these ideas and is distinct from the previous implementation in JUNOS.

What makes a good field name?

To make useful, consistent field names, follow these guidelines:

Use lower case, even for TLAs
Lower case is more civilized. Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and "Xpath" drive your users crazy. Using "xpath" is simpler and better.
Use hyphens, not underscores
Use of hyphens is traditional in XML, and the XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens.
Use full words
Don't abbreviate especially when the abbreviation is not obvious or not widely used. Use "data‑size", not "dsz" or "dsize". Use "interface" instead of "ifname", "if‑name", "iface", "if", or "intf".
Use <verb>-<units>
Using the form <verb>-<units> or <verb>-<classifier>-<units> helps in making consistent, useful names, avoiding the situation where one app uses "sent‑packet" and another "packets‑sent" and another "packets‑we‑have‑sent". The <units> can be dropped when it is obvious, as can obvious words in the classification. Use "receive‑after‑window‑packets" instead of "received‑packets‑of‑data‑after‑window".
Reuse existing field names
Nothing's worse than writing expressions like:
     if ($src1/process[pid == $pid]/name == 
         $src2/proc-table/proc-list
                    /proc-entry[process-id == $pid]/proc-name) {
         ...
     }
 	    

Find someone else who is expressing similar data and follow their fields and hierarchy. Remember the quote is not "Consistency is the hobgoblin of little minds", but "A foolish consistency is the hobgoblin of little minds".

Use containment as scoping
In the previous example, all the names are prefixed with "proc‑", which is redundant given that they are nested under the process table.
Think about your users
Have empathy for your users, choosing clear and useful fields that contain clear and useful data. You may need to augment the display content with xo_attr() calls (Section 5.2.2) or "{e:}" fields (Section 3.2.2.4) to make the data useful.
Don't use an arbitrary number postfix
What does "errors2" mean? No one will know. "errors‑after‑restart" would be a better choice. Think of your users, and think of the future. If you make "errors2", the next guy will happily make "errors3" and before you know it, someone will be asking what's the difference between errors37 and errors63.
Be consistent, uniform, unsurprising, and predictable
Think of your field vocabulary as an API. You want it useful, expressive, meaningful, direct, and obvious. You want the client application's programmer to move between without the need to understand a variety of opinions on how fields are named. They should see the system as a single cohesive whole, not a sack of cats.

Field names constitute the means by which client programmers interact with our system. By choosing wise names now, you are making their lives better.

After using "xolint" to find errors in your field descriptors, use "xolint -V" to spell check your field names and to detect different names for the same data. "dropped‑short" and "dropped‑too‑short" are both reasonable names, but using them both will lead users to ask the difference between the two fields. If there is no difference, use only one of the field names. If there is a difference, change the names to make that difference more obvious.

10.2 
What does this message mean?

Section Contents:

'A percent sign appearing in text is a literal'

The message "A percent sign appearing in text is a literal" can be caused by code like:

     xo_emit("cost: %d", cost);
 	    

This code should be replaced with code like:

     xo_emit("{L:cost}: {:cost/%d}", cost);
 	    

This can be a bit surprising and could be a field that was not properly converted to a libxo-style format string.

'Unknown long name for role/modifier'

The message "Unknown long name for role/modifier" can be caused by code like:

     xo_emit("{,humanization:value}", value);
 	    

This code should be replaced with code like:

     xo_emit("{,humanize:value}", value);
 	    

The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.

'Last character before field definition is a field type'

The message "Last character before field definition is a field type" can be caused by code like:

A common typo:

     xo_emit("{T:Min} T{:Max}");
 	    

This code should be replaced with code like:

     xo_emit("{T:Min} {T:Max}");
 	    

Twiddling the "{" and the field role is a common typo.

'Encoding format uses different number of arguments'

The message "Encoding format uses different number of arguments" can be caused by code like:

     xo_emit("{:name/%6.6s %%04d/%s}", name, number);
 	    

This code should be replaced with code like:

     xo_emit("{:name/%6.6s %04d/%s-%d}", name, number);
 	    

Both format should consume the same number of arguments off the stack

'Only one field role can be used'

The message "Only one field role can be used" can be caused by code like:

     xo_emit("{LT:Max}");
 	    

This code should be replaced with code like:

     xo_emit("{T:Max}");
 	    

'Potential missing slash after C, D, N, L, or T with format'

The message "Potential missing slash after C, D, N, L, or T with format" can be caused by code like:

     xo_emit("{T:%6.6s}\n", "Max");
 	    

This code should be replaced with code like:

     xo_emit("{T:/%6.6s}\n", "Max");
 	    

The "%6.6s" will be a literal, not a field format. While it's possibly valid, it's likely a missing "/".

'An encoding format cannot be given (roles: DNLT)'

The message "An encoding format cannot be given (roles: DNLT)" can be caused by code like:

     xo_emit("{T:Max//%s}", "Max");
 	    

Fields with the C, D, N, L, and T roles are not emitted in the 'encoding' style (JSON, XML), so an encoding format would make no sense.

'Format cannot be given when content is present (roles: CDLN)'

The message "Format cannot be given when content is present (roles: CDLN)" can be caused by code like:

     xo_emit("{N:Max/%6.6s}", "Max");
 	    

Fields with the C, D, L, or N roles can't have both static literal content ("{L:Label}") and a format ("{L:/%s}"). This error will also occur when the content has a backslash in it, like "{N:Type of I/O}"; backslashes should be escaped, like "{N:Type of I\\/O}". Note the double backslash, one for handling 'C' strings, and one for libxo.

'Field has color without fg- or bg- (role: C)'

The message "Field has color without fg- or bg- (role: C)" can be caused by code like:

     xo_emit("{C:green}{:foo}{C:}", x);
 	    

This code should be replaced with code like:

     xo_emit("{C:fg-green}{:foo}{C:}", x);
 	    

Colors must be prefixed by either "fg‑" or "bg‑".

'Field has invalid color or effect (role: C)'

The message "Field has invalid color or effect (role: C)" can be caused by code like:

     xo_emit("{C:fg-purple,bold}{:foo}{C:gween}", x);
 	    

This code should be replaced with code like:

     xo_emit("{C:fg-red,bold}{:foo}{C:fg-green}", x);
 	    

The list of colors and effects are limited. The set of colors includes default, black, red, green, yellow, blue, magenta, cyan, and white, which must be prefixed by either "fg‑" or "bg‑". Effects are limited to bold, no-bold, underline, no-underline, inverse, no-inverse, normal, and reset. Values must be separated by commas.

'Field has humanize modifier but no format string'

The message "Field has humanize modifier but no format string" can be caused by code like:

     xo_emit("{h:value}", value);
 	    

This code should be replaced with code like:

     xo_emit("{h:value/%d}", value);
 	    

Humanization is only value for numbers, which are not likely to use the default format ("%s").

'Field has hn-* modifier but not 'h' modifier'

The message "Field has hn-* modifier but not 'h' modifier" can be caused by code like:

     xo_emit("{,hn-1000:value}", value);
 	    

This code should be replaced with code like:

     xo_emit("{h,hn-1000:value}", value);
 	    

The hn-* modifiers (hn-decimal, hn-space, hn-1000) are only valid for fields with the {h:} modifier.

'Value field must have a name (as content)")'

The message "Value field must have a name (as content)")" can be caused by code like:

     xo_emit("{:/%s}", "value");
 	    

This code should be replaced with code like:

     xo_emit("{:tag-name/%s}", "value");
 	    

The field name is used for XML and JSON encodings. These tags names are static and must appear directly in the field descriptor.

'Use hyphens, not underscores, for value field name'

The message "Use hyphens, not underscores, for value field name" can be caused by code like:

     xo_emit("{:no_under_scores}", "bad");
 	    

This code should be replaced with code like:

     xo_emit("{:no-under-scores}", "bad");
 	    

Use of hyphens is traditional in XML, and the XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens.

'Value field name cannot start with digit'

The message "Value field name cannot start with digit" can be caused by code like:

     xo_emit("{:10-gig/}");
 	    

This code should be replaced with code like:

     xo_emit("{:ten-gig/}");
 	    

XML element names cannot start with a digit.

'Value field name should be lower case'

The message "Value field name should be lower case" can be caused by code like:

     xo_emit("{:WHY-ARE-YOU-SHOUTING}", "NO REASON");
 	    

This code should be replaced with code like:

     xo_emit("{:why-are-you-shouting}", "no reason");
 	    

Lower case is more civilized. Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and "Xpath" drive your users crazy. Lower case rules the seas.

'Value field name should be longer than two characters'

The message "Value field name should be longer than two characters" can be caused by code like:

     xo_emit("{:x}", "mumble");
 	    

This code should be replaced with code like:

     xo_emit("{:something-meaningful}", "mumble");
 	    

Field names should be descriptive, and it's hard to be descriptive in less than two characters. Consider your users and try to make something more useful. Note that this error often occurs when the field type is placed after the colon ("{:T/%20s}"), instead of before it ("{T:/20s}").

'Value field name contains invalid character'

The message "Value field name contains invalid character" can be caused by code like:

     xo_emit("{:cost-in-$$/%u}", 15);
 	    

This code should be replaced with code like:

     xo_emit("{:cost-in-dollars/%u}", 15);
 	    

An invalid character is often a sign of a typo, like "{:]}" instead of "{]:}". Field names are restricted to lower-case characters, digits, and hyphens.

'decoration field contains invalid character'

The message "decoration field contains invalid character" can be caused by code like:

     xo_emit("{D:not good}");
 	    

This code should be replaced with code like:

     xo_emit("{D:((}{:good}{D:))}", "yes");
 	    

This is minor, but fields should use proper roles. Decoration fields are meant to hold punctuation and other characters used to decorate the content, typically to make it more readable to human readers.

'Anchor content should be decimal width'

The message "Anchor content should be decimal width" can be caused by code like:

     xo_emit("{[:mumble}");
 	    

This code should be replaced with code like:

     xo_emit("{[:32}");
 	    

Anchors need an integer value to specify the width of the set of anchored fields. The value can be positive (for left padding/right justification) or negative (for right padding/left justification) and can appear in either the start or stop anchor field descriptor.

'Anchor format should be "%d"'

The message "Anchor format should be "%d"" can be caused by code like:

     xo_emit("{[:/%s}");
 	    

This code should be replaced with code like:

     xo_emit("{[:/%d}");
 	    

Anchors only grok integer values, and if the value is not static, if must be in an 'int' argument, represented by the "%d" format. Anything else is an error.

'Anchor cannot have both format and encoding format")'

The message "Anchor cannot have both format and encoding format")" can be caused by code like:

     xo_emit("{[:32/%d}");
 	    

This code should be replaced with code like:

     xo_emit("{[:32}");
 	    

Anchors can have a static value or argument for the width, but cannot have both.

'Max width only valid for strings'

The message "Max width only valid for strings" can be caused by code like:

     xo_emit("{:tag/%2.4.6d}", 55);
 	    

This code should be replaced with code like:

     xo_emit("{:tag/%2.6d}", 55);
 	    

libxo allows a true 'max width' in addition to the traditional printf-style 'max number of bytes to use for input'. But this is supported only for string values, since it makes no sense for non-strings. This error may occur from a typo, like "{:tag/%6..6d}" where only one period should be used.


11_ 
Howtos: Focused Directions

This section provides task-oriented instructions for selected tasks. If you have a task that needs instructions, please open a request as an enhancement issue on github.

Section Contents:

11.1 
Howto: Report bugs

libxo uses github to track bugs or request enhancements. Please use the following URL:

https://github.com/Juniper/libxo/issues

11.2 
Howto: Install libxo

libxo is open source, under a new BSD license. Source code is available on github, as are recent releases. To get the most current release, please visit:

https://github.com/Juniper/libxo/releases

After downloading and untarring the source code, building involves the following steps:

     sh bin/setup.sh
     cd build
     ../configure
     make
     make test
     sudo make install
 	    

libxo uses a distinct "build" directory to keep generated files separated from source files.

Use "../configure --help" to display available configuration options, which include the following:

   --enable-warnings      Turn on compiler warnings
   --enable-debug         Turn on debugging
   --enable-text-only     Turn on text-only rendering
   --enable-printflike    Enable use of GCC __printflike attribute
   --disable-libxo-options  Turn off support for LIBXO_OPTIONS
   --with-gettext=PFX     Specify location of gettext installation
   --with-libslax-prefix=PFX  Specify location of libslax config
 	    

Compiler warnings are a very good thing, but recent compiler version have added some very pedantic checks. While every attempt is made to keep libxo code warning-free, warnings are now optional. If you are doing development work on libxo, it is required that you use --enable-warnings to keep the code warning free, but most users need not use this option.

libxo provides the --enable-text-only option to reduce the footprint of the library for smaller installations. XML, JSON, and HTML rendering logic is removed.

The gettext library does not provide a simple means of learning its location, but libxo will look for it in /usr and /opt/local. If installed elsewhere, the installer will need to provide this information using the --with-gettext=/dir/path option.

libslax is not required by libxo; it contains the "oxtradoc" program used to format documentation.

For additional information, see Section 2.2.

11.3 
Howto: Convert command line applications

     How do I convert an existing command line application?
 	    

There are three basic steps for converting command line application to use libxo.

  • Setting up the context
  • Converting printf calls
  • Creating hierarchy
  • Converting error functions

Section Contents:

Setting up the context

To use libxo, you'll need to include the "xo.h" header file in your source code files:

     #include <libxo/xo.h>
 	    

In your main() function, you'll need to call xo_parse_args to handling argument parsing (Section 5.4.1). This function removes libxo-specific arguments the program's argv and returns either the number of remaining arguments or -1 to indicate an error.

     int main (int argc, char **argv)
     {
         argc = xo_parse_args(argc, argv);
         if (argc < 0)
             return argc;
         ....
     }
 	    

At the bottom of your main(), you'll need to call xo_finish() to complete output processing for the default handle (Section 5.1). libxo provides the xo_finish_atexit function that is suitable for use with the atexit(3) function.

     atexit(xo_finish_atexit);
 	    

Converting printf Calls

The second task is inspecting code for printf(3) calls and replacing them with xo_emit() calls. The format strings are similar in task, but libxo format strings wrap output fields in braces. The following two calls produce identical text output:

     printf("There are %d %s events\n", count, etype);
     xo_emit("There are {:count/%d} {:event} events\n", count, etype);
 	    

"count" and "event" are used as names for JSON and XML output. The "count" field uses the format "%d" and "event" uses the default "%s" format. Both are "value" roles, which is the default role.

Since text outside of output fields is passed verbatim, other roles are less important, but their proper use can help make output more useful. The "note" and "label" roles allow HTML output to recognize the relationship between text and the associated values, allowing appropriate "hover" and "onclick" behavior. Using the "units" role allows the presentation layer to perform conversions when needed. The "warning" and "error" roles allows use of color and font to draw attention to warnings. The "padding" role makes the use of vital whitespace more clear (Section 3.2.1.6).

The "title" role indicates the headings of table and sections. This allows HTML output to use CSS to make this relationship more obvious.

     printf("Statistics:\n");
     xo_emit("{T:Statistics}:\n");
 	    

The "color" roles controls foreground and background colors, as well as effects like bold and underline (see Section 3.2.1.1).

     xo_emit("{C:bold}required{C:}\n");
 	    

Finally, the start- and stop-anchor roles allow justification and padding over multiple fields (see Section 3.2.1.10).

     snprintf(buf, sizeof(buf), "(%u/%u/%u)", min, ave, max);
     printf("%30s", buf);
 
     xo_emit("{[:30}({:minimum/%u}/{:average/%u}/{:maximum/%u}{]:}",
             min, ave, max);
 	    

Creating Hierarchy

Text output doesn't have any sort of hierarchy, but XML and JSON require this. Typically applications use indentation to represent these relationship:

     printf("table %d\n", tnum);
     for (i = 0; i < tmax; i++) {
         printf("    %s %d\n", table[i].name, table[i].size);
     }
 
     xo_emit("{T:/table %d}\n", tnum);
     xo_open_list("table");
     for (i = 0; i < tmax; i++) {
         xo_open_instance("table");
         xo_emit("{P:    }{k:name} {:size/%d}\n",
                 table[i].name, table[i].size);
         xo_close_instance("table");
     }
     xo_close_list("table");
 	    

The open and close list functions are used before and after the list, and the open and close instance functions are used before and after each instance with in the list.

Typically these developer looks for a "for" loop as an indication of where to put these calls.

In addition, the open and close container functions allow for organization levels of hierarchy.

     printf("Paging information:\n");
     printf("    Free:      %lu\n", free);
     printf("    Active:    %lu\n", active);
     printf("    Inactive:  %lu\n", inactive);
 
     xo_open_container("paging-information");
     xo_emit("{P:    }{L:Free:      }{:free/%lu}\n", free);
     xo_emit("{P:    }{L:Active:    }{:active/%lu}\n", active);
     xo_emit("{P:    }{L:Inactive:  }{:inactive/%lu}\n", inactive);
     xo_close_container("paging-information");
 	    

Converting Error Functions

libxo provides variants of the standard error and warning functions, err(3) and warn(3). There are two variants, one for putting the errors on standard error, and the other writes the errors and warnings to the handle using the appropriate encoding style:

     err(1, "cannot open output file: %s", file);
 
     xo_err(1, "cannot open output file: %s", file);
     xo_emit_err(1, "cannot open output file: {:filename}", file);
 	    

11.5 
Howto: Internationalization (i18n)

     How do I use libxo to support internationalization?
 	    

libxo allows format and field strings to be used a keys into message catalogs to enable translation into a user's native language by invoking the standard gettext(3) functions.

gettext setup is a bit complicated: text strings are extracted from source files into "portable object template" (.pot) files using the "xgettext" command. For each language, this template file is used as the source for a message catalog in the "portable object" (.po) format, which are translated by hand and compiled into "machine object" (.mo) files using the "msgfmt" command. The .mo files are then typically installed in the /usr/share/locale or /opt/local/share/locale directories. At run time, the user's language settings are used to select a .mo file which is searched for matching messages. Text strings in the source code are used as keys to look up the native language strings in the .mo file.

Since the xo_emit format string is used as the key into the message catalog, libxo removes unimportant field formatting and modifiers from the format string before use so that minor formatting changes will not impact the expensive translation process. We don't want a developer change such as changing "/%06d" to "/%08d" to force hand inspection of all .po files. The simplified version can be generated for a single message using the "xopo -s <text>" command, or an entire .pot can be translated using the "xopo -f <input> -o <output>" command.

     EXAMPLE:
         % xopo -s "There are {:count/%u} {:event/%.6s} events\n"
         There are {:count} {:event} events\n
 
     Recommended workflow:
         # Extract text messages
         xgettext --default-domain=foo --no-wrap \
             --add-comments --keyword=xo_emit --keyword=xo_emit_h \
             --keyword=xo_emit_warn -C -E -n --foreign-user \
             -o foo.pot.raw foo.c
 
         # Simplify format strings for libxo
         xopo -f foo.pot.raw -o foo.pot
 
         # For a new language, just copy the file
         cp foo.pot po/LC/my_lang/foo.po
 
         # For an existing language:
         msgmerge --no-wrap po/LC/my_lang/foo.po \
                 foo.pot -o po/LC/my_lang/foo.po.new
 
         # Now the hard part: translate foo.po using tools
         # like poedit or emacs' po-mode
 
         # Compile the finished file; Use of msgfmt's "-v" option is
         # strongly encouraged, so that "fuzzy" entries are reported.
         msgfmt -v -o po/my_lang/LC_MESSAGES/foo.mo po/my_lang/foo.po
 
         # Install the .mo file
         sudo cp po/my_lang/LC_MESSAGES/foo.mo \
                 /opt/local/share/locale/my_lang/LC_MESSAGE/
 	    

Once these steps are complete, you can use the "gettext" command to test the message catalog:

     gettext -d foo -e "some text"
 	    

Section Contents:

i18n and xo_emit

There are three features used in libxo used to support i18n:

  • The "{G:}" role looks for a translation of the format string.
  • The "{g:}" modifier looks for a translation of the field.
  • The "{p:}" modifier looks for a pluralized version of the field.

Together these three flags allows a single function call to give native language support, as well as libxo's normal XML, JSON, and HTML support.

     printf(gettext("Received %zu %s from {g:server} server\n"),
            counter, ngettext("byte", "bytes", counter),
            gettext("web"));
 
     xo_emit("{G:}Received {:received/%zu} {Ngp:byte,bytes} "
             "from {g:server} server\n", counter, "web");
 	    

libxo will see the "{G:}" role and will first simplify the format string, removing field formats and modifiers.

     "Received {:received} {N:byte,bytes} from {:server} server\n"
 	    

libxo calls gettext(3) with that string to get a localized version. If your language were Pig Latin, the result might look like:

     "Eceivedray {:received} {N:byte,bytes} omfray "
                "{:server} erversay\n"
 	    

Note the field names do not change and they should not be translated. The contents of the note ("byte,bytes") should also not be translated, since the "g" modifier will need the untranslated value as the key for the message catalog.

The field "{g:server}" requests the rendered value of the field be translated using gettext(3). In this example, "web" would be used.

The field "{Ngp:byte,bytes}" shows an example of plural form using the "p" modifier with the "g" modifier. The base singular and plural forms appear inside the field, separated by a comma. At run time, libxo uses the previous field's numeric value to decide which form to use by calling ngettext(3).

If a domain name is needed, it can be supplied as the content of the {G:} role. Domain names remain in use throughout the format string until cleared with another domain name.

     printf(dgettext("dns", "Host %s not found: %d(%s)\n"),
         name, errno, dgettext("strerror", strerror(errno)));
 
     xo_emit("{G:dns}Host {:hostname} not found: "
             "%d({G:strerror}{g:%m})\n", name, errno);
 	    

12_ 
Examples

Section Contents:

12.1 
Unit Test

Here is the unit test example:

     int
     main (int argc, char **argv)
     {
         static char base_grocery[] = "GRO";
         static char base_hardware[] = "HRD";
         struct item {
             const char *i_title;
             int i_sold;
             int i_instock;
             int i_onorder;
             const char *i_sku_base;
             int i_sku_num;
         };
         struct item list[] = {
             { "gum", 1412, 54, 10, base_grocery, 415 },
             { "rope", 85, 4, 2, base_hardware, 212 },
             { "ladder", 0, 2, 1, base_hardware, 517 },
             { "bolt", 4123, 144, 42, base_hardware, 632 },
             { "water", 17, 14, 2, base_grocery, 2331 },
             { NULL, 0, 0, 0, NULL, 0 }
         };
         struct item list2[] = {
             { "fish", 1321, 45, 1, base_grocery, 533 },
         };
         struct item *ip;
         xo_info_t info[] = {
             { "in-stock", "number", "Number of items in stock" },
             { "name", "string", "Name of the item" },
             { "on-order", "number", "Number of items on order" },
             { "sku", "string", "Stock Keeping Unit" },
             { "sold", "number", "Number of items sold" },
             { NULL, NULL, NULL },
         };
         int info_count = (sizeof(info) / sizeof(info[0])) - 1;
 
         argc = xo_parse_args(argc, argv);
         if (argc < 0)
             exit(EXIT_FAILURE);
 
         xo_set_info(NULL, info, info_count);
 
         xo_open_container_h(NULL, "top");
 
         xo_open_container("data");
         xo_open_list("item");
 
         for (ip = list; ip->i_title; ip++) {
             xo_open_instance("item");
 
             xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title);
             xo_emit("{P:   }{L:Total sold}: {n:sold/%u%s}\n",
                     ip->i_sold, ip->i_sold ? ".0" : "");
             xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 
                     ip->i_instock);
             xo_emit("{P:   }{Lwc:On order}{:on-order/%u}\n", 
                     ip->i_onorder);
             xo_emit("{P:   }{L:SKU}: {q:sku/%s-000-%u}\n",
                     ip->i_sku_base, ip->i_sku_num);
 
             xo_close_instance("item");
         }
 
         xo_close_list("item");
         xo_close_container("data");
 
         xo_open_container("data");
         xo_open_list("item");
 
         for (ip = list2; ip->i_title; ip++) {
             xo_open_instance("item");
 
             xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title);
             xo_emit("{P:   }{L:Total sold}: {n:sold/%u%s}\n",
                     ip->i_sold, ip->i_sold ? ".0" : "");
             xo_emit("{P:   }{Lwc:In stock}{:in-stock/%u}\n", 
                     ip->i_instock);
             xo_emit("{P:   }{Lwc:On order}{:on-order/%u}\n", 
                     ip->i_onorder);
             xo_emit("{P:   }{L:SKU}: {q:sku/%s-000-%u}\n",
                     ip->i_sku_base, ip->i_sku_num);
 
             xo_close_instance("item");
         }
 
         xo_close_list("item");
         xo_close_container("data");
 
         xo_close_container_h(NULL, "top");
 
         return 0;
     }
 	    

Text output:

     % ./testxo --libxo text
     Item 'gum':
        Total sold: 1412.0
        In stock: 54
        On order: 10
        SKU: GRO-000-415
     Item 'rope':
        Total sold: 85.0
        In stock: 4
        On order: 2
        SKU: HRD-000-212
     Item 'ladder':
        Total sold: 0
        In stock: 2
        On order: 1
        SKU: HRD-000-517
     Item 'bolt':
        Total sold: 4123.0
        In stock: 144
        On order: 42
        SKU: HRD-000-632
     Item 'water':
        Total sold: 17.0
        In stock: 14
        On order: 2
        SKU: GRO-000-2331
     Item 'fish':
        Total sold: 1321.0
        In stock: 45
        On order: 1
        SKU: GRO-000-533
 	    

JSON output:

     % ./testxo --libxo json,pretty
     "top": {
       "data": {
         "item": [
           {
             "name": "gum",
             "sold": 1412.0,
             "in-stock": 54,
             "on-order": 10,
             "sku": "GRO-000-415"
           },
           {
             "name": "rope",
             "sold": 85.0,
             "in-stock": 4,
             "on-order": 2,
             "sku": "HRD-000-212"
           },
           {
             "name": "ladder",
             "sold": 0,
             "in-stock": 2,
             "on-order": 1,
             "sku": "HRD-000-517"
           },
           {
             "name": "bolt",
             "sold": 4123.0,
             "in-stock": 144,
             "on-order": 42,
             "sku": "HRD-000-632"
           },
           {
             "name": "water",
             "sold": 17.0,
             "in-stock": 14,
             "on-order": 2,
             "sku": "GRO-000-2331"
           }
         ]
       },
       "data": {
         "item": [
           {
             "name": "fish",
             "sold": 1321.0,
             "in-stock": 45,
             "on-order": 1,
             "sku": "GRO-000-533"
           }
         ]
       }
     }
 	    

XML output:

     % ./testxo --libxo pretty,xml
     <top>
       <data>
         <item>
           <name>gum</name>
           <sold>1412.0</sold>
           <in-stock>54</in-stock>
           <on-order>10</on-order>
           <sku>GRO-000-415</sku>
         </item>
         <item>
           <name>rope</name>
           <sold>85.0</sold>
           <in-stock>4</in-stock>
           <on-order>2</on-order>
           <sku>HRD-000-212</sku>
         </item>
         <item>
           <name>ladder</name>
           <sold>0</sold>
           <in-stock>2</in-stock>
           <on-order>1</on-order>
           <sku>HRD-000-517</sku>
         </item>
         <item>
           <name>bolt</name>
           <sold>4123.0</sold>
           <in-stock>144</in-stock>
           <on-order>42</on-order>
           <sku>HRD-000-632</sku>
         </item>
         <item>
           <name>water</name>
           <sold>17.0</sold>
           <in-stock>14</in-stock>
           <on-order>2</on-order>
           <sku>GRO-000-2331</sku>
         </item>
       </data>
       <data>
         <item>
           <name>fish</name>
           <sold>1321.0</sold>
           <in-stock>45</in-stock>
           <on-order>1</on-order>
           <sku>GRO-000-533</sku>
         </item>
       </data>
     </top>
 	    

HMTL output:

     % ./testxo --libxo pretty,html
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">gum</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">1412.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">54</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">10</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">GRO-000-415</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">rope</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">85.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">4</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">HRD-000-212</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">ladder</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">1</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">HRD-000-517</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">bolt</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">4123.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">144</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">42</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">HRD-000-632</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">water</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">17.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">14</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">GRO-000-2331</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name">fish</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold">1321.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock">45</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order">1</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku">GRO-000-533</div>
     </div>
 	    

HTML output with xpath and info flags:

     % ./testxo --libxo pretty,html,xpath,info
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">gum</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">1412.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">54</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">10</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">GRO-000-415</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">rope</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">85.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">4</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">HRD-000-212</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">ladder</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">1</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">HRD-000-517</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">bolt</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">4123.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">144</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">42</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">HRD-000-632</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">water</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">17.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">14</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">2</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">GRO-000-2331</div>
     </div>
     <div class="line">
       <div class="label">Item</div>
       <div class="text"> '</div>
       <div class="data" data-tag="name"
            data-xpath="/top/data/item/name" data-type="string"
            data-help="Name of the item">fish</div>
       <div class="text">':</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">Total sold</div>
       <div class="text">: </div>
       <div class="data" data-tag="sold"
            data-xpath="/top/data/item/sold" data-type="number"
            data-help="Number of items sold">1321.0</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">In stock</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="in-stock"
            data-xpath="/top/data/item/in-stock" data-type="number"
            data-help="Number of items in stock">45</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">On order</div>
       <div class="decoration">:</div>
       <div class="padding"> </div>
       <div class="data" data-tag="on-order"
            data-xpath="/top/data/item/on-order" data-type="number"
            data-help="Number of items on order">1</div>
     </div>
     <div class="line">
       <div class="padding">   </div>
       <div class="label">SKU</div>
       <div class="text">: </div>
       <div class="data" data-tag="sku"
            data-xpath="/top/data/item/sku" data-type="string"
            data-help="Stock Keeping Unit">GRO-000-533</div>
     </div>
 	    

Author's Address

Phil ShaferJuniper NetworksEMail:
Index: projects/make-check-sandbox/contrib/libxo/libxo/libxo.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/libxo.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/libxo.3 (revision 322022) @@ -1,313 +1,323 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 8, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm libxo .Nd library for emitting text, XML, JSON, or HTML output .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Sh DESCRIPTION The functions defined in .Nm are used to generate a choice of .Em TEXT , .Em XML , .Em JSON , or .Em HTML output. A common set of functions are used, with command line switches passed to the library to control the details of the output. .Pp Most commands emit text output aimed at humans. It is designed to be parsed and understood by a user. Humans are gifted at extracting details and pattern matching. Often programmers need to extract information from this human-oriented output. Programmers use tools like .Xr grep 1 , .Xr awk 1 , and regular expressions to ferret out the pieces of information they need. Such solutions are fragile and require updates when output contents change or evolve, requiring testing and validation. .Pp Modern tool developers favor encoding schemes like XML and JSON, which allow trivial parsing and extraction of data. Such formats are simple, well understood, hierarchical, easily parsed, and often integrate easier with common tools and environments. .Pp In addition, modern reality means that more output ends up in web browsers than in terminals, making HTML output valuable. .Pp .Nm allows a single set of function calls in source code to generate traditional text output, as well as XML and JSON formatted data. HTML can also be generated; "
" elements surround the traditional text output, with attributes that detail how to render the data. .Pp There are four encoding styles supported by .Nm : .Bl -bullet .It TEXT output can be display on a terminal session, allowing compatibility with traditional command line usage. .It XML output is suitable for tools like XPath and protocols like NETCONF. .It JSON output can be used for RESTful APIs and integration with languages like Javascript and Python. .It HTML can be matched with a small CSS file to permit rendering in any HTML5 browser. .El .Pp In general, XML and JSON are suitable for encoding data, while TEXT is suited for terminal output and HTML is suited for display in a web browser (see .Xr xohtml 1 ). .Pp The .Nm library allows an application to generate text, XML, JSON, and HTML output using a common set of function calls. The application decides at run time which output style should be produced. The application calls a function .Xr xo_emit 3 to product output that is described in a format string. A .Dq field descriptor tells .Nm what the field is and what it means. Each field descriptor is placed in braces with a printf-like format string: .Bd -literal -offset indent xo_emit(" {:lines/%7ju} {:words/%7ju} " "{:characters/%7ju}{d:filename/%s}\\n", linect, wordct, charct, file); .Ed .Pp Each field can have a role, with the 'value' role being the default, and the role tells .Nm how and when to render that field, as well as a .Xr printf 3 Ns -like format string. .Pp Output can then be generated in various style, using the "--libxo" option. .Sh DEFAULT HANDLE Handles give an abstraction for .Nm that encapsulates the state of a stream of output. Handles have the data type "xo_handle_t" and are opaque to the caller. .Pp The library has a default handle that is automatically initialized. By default, this handle will send text style output to standard output. The .Xr xo_set_style 3 and .Xr xo_set_flags 3 functions can be used to change this behavior. .Pp Many .Nm functions take a handle as their first parameter; most that do not use the default handle. Any function taking a handle can be passed .Dv NULL to access the default handle. .Pp For the typical command that is generating output on standard output, there is no need to create an explicit handle, but they are available when needed, e.g., for daemons that generate multiple streams of output. .Sh FUNCTION OVERVIEW The .Nm library includes the following functions: .Bl -tag -width "xo_close_container_hd" .It Sy "Function Description" .It Fn xo_attr .It Fn xo_attr_h .It Fn xo_attr_hv Allows the caller to emit XML attributes with the next open element. .It Fn xo_create .It Fn xo_create_to_file Allow the caller to create a new handle. Note that .Nm has a default handle that allows the caller to avoid use of an explicitly created handle. Only callers writing to files other than .Dv stdout would need to call .Fn xo_create . .It Fn xo_destroy Frees any resources associated with the handle, including the handle itself. .It Fn xo_emit .It Fn xo_emit_h .It Fn xo_emit_hv Emit formatted output. The .Fa fmt string controls the conversion of the remaining arguments into formatted output. See .Xr xo_format 5 for details. .It Fn xo_emit_warn .It Fn xo_emit_warnx .It Fn xo_emit_warn_c .It Fn xo_emit_warn_hc .It Fn xo_emit_err .It Fn xo_emit_errc .It Fn xo_emit_errx These functions are mildly compatible with their standard libc namesakes, but use the format string defined in .Xr xo_format 5 . While there is an increased cost for converting the strings, the output provided can be richer and more useful. See also .Xr xo_err 3 .It Fn xo_warn .It Fn xo_warnx .It Fn xo_warn_c .It Fn xo_warn_hc .It Fn xo_err .It Fn xo_errc .It Fn xo_errx .It Fn xo_message .It Fn xo_message_c .It Fn xo_message_hc .It Fn xo_message_hcv These functions are meant to be compatible with their standard libc namesakes. .It Fn xo_finish .It Fn xo_finish_h Flush output, close open construct, and complete any pending operations. .It Fn xo_flush .It Fn xo_flush_h Allow the caller to flush any pending output for a handle. .It Fn xo_no_setlocale Direct .Nm to avoid initializing the locale. This function should be called before any other .Nm function is called. .It Fn xo_open_container .It Fn xo_open_container_h .It Fn xo_open_container_hd .It Fn xo_open_container_d .It Fn xo_close_container .It Fn xo_close_container_h .It Fn xo_close_container_hd .It Fn xo_close_container_d Containers a singleton levels of hierarchy, typically used to organize related content. .It Fn xo_open_list_h .It Fn xo_open_list .It Fn xo_open_list_hd .It Fn xo_open_list_d .It Fn xo_open_instance_h .It Fn xo_open_instance .It Fn xo_open_instance_hd .It Fn xo_open_instance_d .It Fn xo_close_instance_h .It Fn xo_close_instance .It Fn xo_close_instance_hd .It Fn xo_close_instance_d .It Fn xo_close_list_h .It Fn xo_close_list .It Fn xo_close_list_hd .It Fn xo_close_list_d Lists are levels of hierarchy that can appear multiple times within the same parent. Two calls are needed to encapsulate them, one for the list and one for each instance of that list. Typically .Fn xo_open_list and .Fn xo_close_list are called outside a for-loop, where .Fn xo_open_instance it called at the top of the loop, and .Fn xo_close_instance is called at the bottom of the loop. .It Fn xo_parse_args Inspects command line arguments for directions to .Nm . This function should be called before .Va argv is inspected by the application. .It Fn xo_set_allocator Instructs .Nm to use an alternative memory allocator and deallocator. .It Fn xo_set_flags .It Fn xo_clear_flags Change the flags set for a handle. .It Fn xo_set_info Provides additional information about elements for use with HTML rendering. .It Fn xo_set_options Changes formatting options used by handle. .It Fn xo_set_style .It Fn xo_set_style_name Changes the output style used by a handle. .It Fn xo_set_writer Instructs .Nm to use an alternative set of low-level output functions. .El .Sh SEE ALSO .Xr xo 1 , .Xr xolint 1 , .Xr xo_attr 3 , .Xr xo_create 3 , .Xr xo_emit 3 , .Xr xo_emit_err 3 , .Xr xo_err 3 , .Xr xo_finish 3 , .Xr xo_flush 3 , .Xr xo_no_setlocale 3 , .Xr xo_open_container 3 , .Xr xo_open_list 3 , .Xr xo_parse_args 3 , .Xr xo_set_allocator 3 , .Xr xo_set_flags 3 , .Xr xo_set_info 3 , .Xr xo_set_options 3 , .Xr xo_set_style 3 , .Xr xo_set_writer 3 , .Xr xo_format 5 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/libxo.c =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/libxo.c (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/libxo.c (revision 322022) @@ -1,8313 +1,8351 @@ /* * Copyright (c) 2014-2015, Juniper Networks, Inc. * All rights reserved. * This SOFTWARE is licensed under the LICENSE provided in the * ../Copyright file. By downloading, installing, copying, or otherwise * using the SOFTWARE, you agree to be bound by the terms of that * LICENSE. * Phil Shafer, July 2014 * * This is the implementation of libxo, the formatting library that * generates multiple styles of output from a single code path. * Command line utilities can have their normal text output while * automation tools can see XML or JSON output, and web tools can use * HTML output that encodes the text output annotated with additional * information. Specialized encoders can be built that allow custom * encoding including binary ones like CBOR, thrift, protobufs, etc. * * Full documentation is available in ./doc/libxo.txt or online at: * http://juniper.github.io/libxo/libxo-manual.html * * For first time readers, the core bits of code to start looking at are: * - xo_do_emit() -- parse and emit a set of fields * - xo_do_emit_fields -- the central function of the library * - xo_do_format_field() -- handles formatting a single field * - xo_transiton() -- the state machine that keeps things sane * and of course the "xo_handle_t" data structure, which carries all * configuration and state. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "xo_config.h" #include "xo.h" #include "xo_encoder.h" #include "xo_buf.h" /* * We ask wcwidth() to do an impossible job, really. It's supposed to * need to tell us the number of columns consumed to display a unicode * character. It returns that number without any sort of context, but * we know they are characters whose glyph differs based on placement * (end of word, middle of word, etc) and many that affect characters * previously emitted. Without content, it can't hope to tell us. * But it's the only standard tool we've got, so we use it. We would * use wcswidth() but it typically just loops through adding the results * of wcwidth() calls in an entirely unhelpful way. * * Even then, there are many poor implementations (macosx), so we have * to carry our own. We could have configure.ac test this (with * something like 'assert(wcwidth(0x200d) == 0)'), but it would have * to run a binary, which breaks cross-compilation. Hmm... I could * run this test at init time and make a warning for our dear user. * * Anyhow, it remains a best-effort sort of thing. And it's all made * more hopeless because we assume the display code doing the rendering is * playing by the same rules we are. If it display 0x200d as a square * box or a funky question mark, the output will be hosed. */ #ifdef LIBXO_WCWIDTH #include "xo_wcwidth.h" #else /* LIBXO_WCWIDTH */ #define xo_wcwidth(_x) wcwidth(_x) #endif /* LIBXO_WCWIDTH */ #ifdef HAVE_STDIO_EXT_H #include #endif /* HAVE_STDIO_EXT_H */ /* * humanize_number is a great function, unless you don't have it. So * we carry one in our pocket. */ #ifdef HAVE_HUMANIZE_NUMBER #include #define xo_humanize_number humanize_number #else /* HAVE_HUMANIZE_NUMBER */ #include "xo_humanize.h" #endif /* HAVE_HUMANIZE_NUMBER */ #ifdef HAVE_GETTEXT #include #endif /* HAVE_GETTEXT */ /* Rather lame that we can't count on these... */ #ifndef FALSE #define FALSE 0 #endif #ifndef TRUE #define TRUE 1 #endif /* * Three styles of specifying thread-local variables are supported. * configure.ac has the brains to run each possibility through the * compiler and see what works; we are left to define the THREAD_LOCAL * macro to the right value. Most toolchains (clang, gcc) use * "before", but some (borland) use "after" and I've heard of some * (ms) that use __declspec. Any others out there? */ #define THREAD_LOCAL_before 1 #define THREAD_LOCAL_after 2 #define THREAD_LOCAL_declspec 3 #ifndef HAVE_THREAD_LOCAL #define THREAD_LOCAL(_x) _x #elif HAVE_THREAD_LOCAL == THREAD_LOCAL_before #define THREAD_LOCAL(_x) __thread _x #elif HAVE_THREAD_LOCAL == THREAD_LOCAL_after #define THREAD_LOCAL(_x) _x __thread #elif HAVE_THREAD_LOCAL == THREAD_LOCAL_declspec #define THREAD_LOCAL(_x) __declspec(_x) #else #error unknown thread-local setting #endif /* HAVE_THREADS_H */ const char xo_version[] = LIBXO_VERSION; const char xo_version_extra[] = LIBXO_VERSION_EXTRA; static const char xo_default_format[] = "%s"; #ifndef UNUSED #define UNUSED __attribute__ ((__unused__)) #endif /* UNUSED */ #define XO_INDENT_BY 2 /* Amount to indent when pretty printing */ #define XO_DEPTH 128 /* Default stack depth */ -#define XO_MAX_ANCHOR_WIDTH (8*1024) /* Anything wider is just sillyb */ +#define XO_MAX_ANCHOR_WIDTH (8*1024) /* Anything wider is just silly */ #define XO_FAILURE_NAME "failure" /* Flags for the stack frame */ typedef unsigned xo_xsf_flags_t; /* XSF_* flags */ #define XSF_NOT_FIRST (1<<0) /* Not the first element */ #define XSF_LIST (1<<1) /* Frame is a list */ #define XSF_INSTANCE (1<<2) /* Frame is an instance */ #define XSF_DTRT (1<<3) /* Save the name for DTRT mode */ #define XSF_CONTENT (1<<4) /* Some content has been emitted */ #define XSF_EMIT (1<<5) /* Some field has been emitted */ #define XSF_EMIT_KEY (1<<6) /* A key has been emitted */ #define XSF_EMIT_LEAF_LIST (1<<7) /* A leaf-list field has been emitted */ /* These are the flags we propagate between markers and their parents */ #define XSF_MARKER_FLAGS \ (XSF_NOT_FIRST | XSF_CONTENT | XSF_EMIT | XSF_EMIT_KEY | XSF_EMIT_LEAF_LIST ) /* * A word about states: We use a finite state machine (FMS) approach * to help remove fragility from the caller's code. Instead of * requiring a specific order of calls, we'll allow the caller more * flexibility and make the library responsible for recovering from * missed steps. The goal is that the library should not be capable * of emitting invalid xml or json, but the developer shouldn't need * to know or understand all the details about these encodings. * * You can think of states as either states or events, since they * function rather like both. None of the XO_CLOSE_* events will * persist as states, since the matching stack frame will be popped. * Same is true of XSS_EMIT, which is an event that asks us to * prep for emitting output fields. */ /* Stack frame states */ typedef unsigned xo_state_t; #define XSS_INIT 0 /* Initial stack state */ #define XSS_OPEN_CONTAINER 1 #define XSS_CLOSE_CONTAINER 2 #define XSS_OPEN_LIST 3 #define XSS_CLOSE_LIST 4 #define XSS_OPEN_INSTANCE 5 #define XSS_CLOSE_INSTANCE 6 #define XSS_OPEN_LEAF_LIST 7 #define XSS_CLOSE_LEAF_LIST 8 #define XSS_DISCARDING 9 /* Discarding data until recovered */ #define XSS_MARKER 10 /* xo_open_marker's marker */ #define XSS_EMIT 11 /* xo_emit has a leaf field */ #define XSS_EMIT_LEAF_LIST 12 /* xo_emit has a leaf-list ({l:}) */ #define XSS_FINISH 13 /* xo_finish was called */ #define XSS_MAX 13 #define XSS_TRANSITION(_old, _new) ((_old) << 8 | (_new)) /* * xo_stack_t: As we open and close containers and levels, we * create a stack of frames to track them. This is needed for * XOF_WARN and XOF_XPATH. */ typedef struct xo_stack_s { xo_xsf_flags_t xs_flags; /* Flags for this frame */ xo_state_t xs_state; /* State for this stack frame */ char *xs_name; /* Name (for XPath value) */ char *xs_keys; /* XPath predicate for any key fields */ } xo_stack_t; /* * libxo supports colors and effects, for those who like them. * XO_COL_* ("colors") refers to fancy ansi codes, while X__EFF_* * ("effects") are bits since we need to maintain state. */ typedef uint8_t xo_color_t; #define XO_COL_DEFAULT 0 #define XO_COL_BLACK 1 #define XO_COL_RED 2 #define XO_COL_GREEN 3 #define XO_COL_YELLOW 4 #define XO_COL_BLUE 5 #define XO_COL_MAGENTA 6 #define XO_COL_CYAN 7 #define XO_COL_WHITE 8 #define XO_NUM_COLORS 9 /* * Yes, there's no blink. We're civilized. We like users. Blink * isn't something one does to someone you like. Friends don't let * friends use blink. On friends. You know what I mean. Blink is * like, well, it's like bursting into show tunes at a funeral. It's * just not done. Not something anyone wants. And on those rare * instances where it might actually be appropriate, it's still wrong, * since it's likely done by the wrong person for the wrong reason. * Just like blink. And if I implemented blink, I'd be like a funeral * director who adds "Would you like us to burst into show tunes?" on * the list of questions asked while making funeral arrangements. * It's formalizing wrongness in the wrong way. And we're just too * civilized to do that. Hhhmph! */ #define XO_EFF_RESET (1<<0) #define XO_EFF_NORMAL (1<<1) #define XO_EFF_BOLD (1<<2) #define XO_EFF_UNDERLINE (1<<3) #define XO_EFF_INVERSE (1<<4) #define XO_EFF_CLEAR_BITS XO_EFF_RESET /* Reset gets reset, surprisingly */ typedef uint8_t xo_effect_t; typedef struct xo_colors_s { xo_effect_t xoc_effects; /* Current effect set */ xo_color_t xoc_col_fg; /* Foreground color */ xo_color_t xoc_col_bg; /* Background color */ } xo_colors_t; /* * xo_handle_t: this is the principle data structure for libxo. * It's used as a store for state, options, content, and all manor * of other information. */ struct xo_handle_s { xo_xof_flags_t xo_flags; /* Flags (XOF_*) from the user*/ xo_xof_flags_t xo_iflags; /* Internal flags (XOIF_*) */ xo_style_t xo_style; /* XO_STYLE_* value */ unsigned short xo_indent; /* Indent level (if pretty) */ unsigned short xo_indent_by; /* Indent amount (tab stop) */ xo_write_func_t xo_write; /* Write callback */ xo_close_func_t xo_close; /* Close callback */ xo_flush_func_t xo_flush; /* Flush callback */ xo_formatter_t xo_formatter; /* Custom formating function */ xo_checkpointer_t xo_checkpointer; /* Custom formating support function */ void *xo_opaque; /* Opaque data for write function */ xo_buffer_t xo_data; /* Output data */ xo_buffer_t xo_fmt; /* Work area for building format strings */ xo_buffer_t xo_attrs; /* Work area for building XML attributes */ xo_buffer_t xo_predicate; /* Work area for building XPath predicates */ xo_stack_t *xo_stack; /* Stack pointer */ int xo_depth; /* Depth of stack */ int xo_stack_size; /* Size of the stack */ xo_info_t *xo_info; /* Info fields for all elements */ int xo_info_count; /* Number of info entries */ va_list xo_vap; /* Variable arguments (stdargs) */ char *xo_leading_xpath; /* A leading XPath expression */ mbstate_t xo_mbstate; /* Multi-byte character conversion state */ ssize_t xo_anchor_offset; /* Start of anchored text */ ssize_t xo_anchor_columns; /* Number of columns since the start anchor */ ssize_t xo_anchor_min_width; /* Desired width of anchored text */ ssize_t xo_units_offset; /* Start of units insertion point */ ssize_t xo_columns; /* Columns emitted during this xo_emit call */ #ifndef LIBXO_TEXT_ONLY uint8_t xo_color_map_fg[XO_NUM_COLORS]; /* Foreground color mappings */ uint8_t xo_color_map_bg[XO_NUM_COLORS]; /* Background color mappings */ #endif /* LIBXO_TEXT_ONLY */ xo_colors_t xo_colors; /* Current color and effect values */ xo_buffer_t xo_color_buf; /* HTML: buffer of colors and effects */ char *xo_version; /* Version string */ int xo_errno; /* Saved errno for "%m" */ char *xo_gt_domain; /* Gettext domain, suitable for dgettext(3) */ xo_encoder_func_t xo_encoder; /* Encoding function */ void *xo_private; /* Private data for external encoders */ }; /* Flag operations */ #define XOF_BIT_ISSET(_flag, _bit) (((_flag) & (_bit)) ? 1 : 0) #define XOF_BIT_SET(_flag, _bit) do { (_flag) |= (_bit); } while (0) #define XOF_BIT_CLEAR(_flag, _bit) do { (_flag) &= ~(_bit); } while (0) #define XOF_ISSET(_xop, _bit) XOF_BIT_ISSET(_xop->xo_flags, _bit) #define XOF_SET(_xop, _bit) XOF_BIT_SET(_xop->xo_flags, _bit) #define XOF_CLEAR(_xop, _bit) XOF_BIT_CLEAR(_xop->xo_flags, _bit) #define XOIF_ISSET(_xop, _bit) XOF_BIT_ISSET(_xop->xo_iflags, _bit) #define XOIF_SET(_xop, _bit) XOF_BIT_SET(_xop->xo_iflags, _bit) #define XOIF_CLEAR(_xop, _bit) XOF_BIT_CLEAR(_xop->xo_iflags, _bit) /* Internal flags */ #define XOIF_REORDER XOF_BIT(0) /* Reordering fields; record field info */ #define XOIF_DIV_OPEN XOF_BIT(1) /* A
is open */ #define XOIF_TOP_EMITTED XOF_BIT(2) /* The top JSON braces have been emitted */ #define XOIF_ANCHOR XOF_BIT(3) /* An anchor is in place */ #define XOIF_UNITS_PENDING XOF_BIT(4) /* We have a units-insertion pending */ #define XOIF_INIT_IN_PROGRESS XOF_BIT(5) /* Init of handle is in progress */ /* Flags for formatting functions */ typedef unsigned long xo_xff_flags_t; #define XFF_COLON (1<<0) /* Append a ":" */ #define XFF_COMMA (1<<1) /* Append a "," iff there's more output */ #define XFF_WS (1<<2) /* Append a blank */ #define XFF_ENCODE_ONLY (1<<3) /* Only emit for encoding styles (XML, JSON) */ #define XFF_QUOTE (1<<4) /* Force quotes */ #define XFF_NOQUOTE (1<<5) /* Force no quotes */ #define XFF_DISPLAY_ONLY (1<<6) /* Only emit for display styles (text, html) */ #define XFF_KEY (1<<7) /* Field is a key (for XPath) */ #define XFF_XML (1<<8) /* Force XML encoding style (for XPath) */ #define XFF_ATTR (1<<9) /* Escape value using attribute rules (XML) */ #define XFF_BLANK_LINE (1<<10) /* Emit a blank line */ #define XFF_NO_OUTPUT (1<<11) /* Do not make any output */ #define XFF_TRIM_WS (1<<12) /* Trim whitespace off encoded values */ #define XFF_LEAF_LIST (1<<13) /* A leaf-list (list of values) */ #define XFF_UNESCAPE (1<<14) /* Need to printf-style unescape the value */ #define XFF_HUMANIZE (1<<15) /* Humanize the value (for display styles) */ #define XFF_HN_SPACE (1<<16) /* Humanize: put space before suffix */ #define XFF_HN_DECIMAL (1<<17) /* Humanize: add one decimal place if <10 */ #define XFF_HN_1000 (1<<18) /* Humanize: use 1000, not 1024 */ #define XFF_GT_FIELD (1<<19) /* Call gettext() on a field */ #define XFF_GT_PLURAL (1<<20) /* Call dngettext to find plural form */ #define XFF_ARGUMENT (1<<21) /* Content provided via argument */ /* Flags to turn off when we don't want i18n processing */ #define XFF_GT_FLAGS (XFF_GT_FIELD | XFF_GT_PLURAL) /* * Normal printf has width and precision, which for strings operate as * min and max number of columns. But this depends on the idea that * one byte means one column, which UTF-8 and multi-byte characters * pitches on its ear. It may take 40 bytes of data to populate 14 * columns, but we can't go off looking at 40 bytes of data without the * caller's permission for fear/knowledge that we'll generate core files. * * So we make three values, distinguishing between "max column" and * "number of bytes that we will inspect inspect safely" We call the * later "size", and make the format "%[[].[[].]]s". * * Under the "first do no harm" theory, we default "max" to "size". * This is a reasonable assumption for folks that don't grok the * MBS/WCS/UTF-8 world, and while it will be annoying, it will never * be evil. * * For example, xo_emit("{:tag/%-14.14s}", buf) will make 14 * columns of output, but will never look at more than 14 bytes of the * input buffer. This is mostly compatible with printf and caller's * expectations. * * In contrast xo_emit("{:tag/%-14..14s}", buf) will look at however * many bytes (or until a NUL is seen) are needed to fill 14 columns * of output. xo_emit("{:tag/%-14.*.14s}", xx, buf) will look at up * to xx bytes (or until a NUL is seen) in order to fill 14 columns * of output. * * It's fairly amazing how a good idea (handle all languages of the * world) blows such a big hole in the bottom of the fairly weak boat * that is C string handling. The simplicity and completenesss are * sunk in ways we haven't even begun to understand. */ #define XF_WIDTH_MIN 0 /* Minimal width */ #define XF_WIDTH_SIZE 1 /* Maximum number of bytes to examine */ #define XF_WIDTH_MAX 2 /* Maximum width */ #define XF_WIDTH_NUM 3 /* Numeric fields in printf (min.size.max) */ /* Input and output string encodings */ #define XF_ENC_WIDE 1 /* Wide characters (wchar_t) */ #define XF_ENC_UTF8 2 /* UTF-8 */ #define XF_ENC_LOCALE 3 /* Current locale */ /* * A place to parse printf-style format flags for each field */ typedef struct xo_format_s { unsigned char xf_fc; /* Format character */ unsigned char xf_enc; /* Encoding of the string (XF_ENC_*) */ unsigned char xf_skip; /* Skip this field */ unsigned char xf_lflag; /* 'l' (long) */ unsigned char xf_hflag;; /* 'h' (half) */ unsigned char xf_jflag; /* 'j' (intmax_t) */ unsigned char xf_tflag; /* 't' (ptrdiff_t) */ unsigned char xf_zflag; /* 'z' (size_t) */ unsigned char xf_qflag; /* 'q' (quad_t) */ unsigned char xf_seen_minus; /* Seen a minus */ int xf_leading_zero; /* Seen a leading zero (zero fill) */ unsigned xf_dots; /* Seen one or more '.'s */ int xf_width[XF_WIDTH_NUM]; /* Width/precision/size numeric fields */ unsigned xf_stars; /* Seen one or more '*'s */ unsigned char xf_star[XF_WIDTH_NUM]; /* Seen one or more '*'s */ } xo_format_t; /* * This structure represents the parsed field information, suitable for * processing by xo_do_emit and anything else that needs to parse fields. * Note that all pointers point to the main format string. * * XXX This is a first step toward compilable or cachable format * strings. We can also cache the results of dgettext when no format * is used, assuming the 'p' modifier has _not_ been set. */ typedef struct xo_field_info_s { xo_xff_flags_t xfi_flags; /* Flags for this field */ unsigned xfi_ftype; /* Field type, as character (e.g. 'V') */ const char *xfi_start; /* Start of field in the format string */ const char *xfi_content; /* Field's content */ const char *xfi_format; /* Field's Format */ const char *xfi_encoding; /* Field's encoding format */ const char *xfi_next; /* Next character in format string */ ssize_t xfi_len; /* Length of field */ ssize_t xfi_clen; /* Content length */ ssize_t xfi_flen; /* Format length */ ssize_t xfi_elen; /* Encoding length */ unsigned xfi_fnum; /* Field number (if used; 0 otherwise) */ unsigned xfi_renum; /* Reordered number (0 == no renumbering) */ } xo_field_info_t; /* * We keep a 'default' handle to allow callers to avoid having to * allocate one. Passing NULL to any of our functions will use * this default handle. Most functions have a variant that doesn't * require a handle at all, since most output is to stdout, which * the default handle handles handily. */ static THREAD_LOCAL(xo_handle_t) xo_default_handle; static THREAD_LOCAL(int) xo_default_inited; static int xo_locale_inited; static const char *xo_program; /* * To allow libxo to be used in diverse environment, we allow the * caller to give callbacks for memory allocation. */ xo_realloc_func_t xo_realloc = realloc; xo_free_func_t xo_free = free; /* Forward declarations */ static void xo_failure (xo_handle_t *xop, const char *fmt, ...); static ssize_t xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name, xo_state_t new_state); static int xo_set_options_simple (xo_handle_t *xop, const char *input); static int xo_color_find (const char *str); static void xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, const char *name, ssize_t nlen, const char *value, ssize_t vlen, const char *fmt, ssize_t flen, const char *encoding, ssize_t elen); static void xo_anchor_clear (xo_handle_t *xop); /* * xo_style is used to retrieve the current style. When we're built * for "text only" mode, we use this function to drive the removal * of most of the code in libxo. We return a constant and the compiler * happily removes the non-text code that is not longer executed. This * trims our code nicely without needing to trampel perfectly readable * code with ifdefs. */ static inline xo_style_t xo_style (xo_handle_t *xop UNUSED) { #ifdef LIBXO_TEXT_ONLY return XO_STYLE_TEXT; #else /* LIBXO_TEXT_ONLY */ return xop->xo_style; #endif /* LIBXO_TEXT_ONLY */ } /* * Callback to write data to a FILE pointer */ static xo_ssize_t xo_write_to_file (void *opaque, const char *data) { FILE *fp = (FILE *) opaque; return fprintf(fp, "%s", data); } /* * Callback to close a file */ static void xo_close_file (void *opaque) { FILE *fp = (FILE *) opaque; fclose(fp); } /* * Callback to flush a FILE pointer */ static int xo_flush_file (void *opaque) { FILE *fp = (FILE *) opaque; return fflush(fp); } /* * Use a rotating stock of buffers to make a printable string */ #define XO_NUMBUFS 8 #define XO_SMBUFSZ 128 static const char * xo_printable (const char *str) { static THREAD_LOCAL(char) bufset[XO_NUMBUFS][XO_SMBUFSZ]; static THREAD_LOCAL(int) bufnum = 0; if (str == NULL) return ""; if (++bufnum == XO_NUMBUFS) bufnum = 0; char *res = bufset[bufnum], *cp, *ep; for (cp = res, ep = res + XO_SMBUFSZ - 1; *str && cp < ep; cp++, str++) { if (*str == '\n') { *cp++ = '\\'; *cp = 'n'; } else if (*str == '\r') { *cp++ = '\\'; *cp = 'r'; } else if (*str == '\"') { *cp++ = '\\'; *cp = '"'; } else *cp = *str; } *cp = '\0'; return res; } static int xo_depth_check (xo_handle_t *xop, int depth) { xo_stack_t *xsp; if (depth >= xop->xo_stack_size) { depth += XO_DEPTH; /* Extra room */ xsp = xo_realloc(xop->xo_stack, sizeof(xop->xo_stack[0]) * depth); if (xsp == NULL) { xo_failure(xop, "xo_depth_check: out of memory (%d)", depth); return -1; } int count = depth - xop->xo_stack_size; bzero(xsp + xop->xo_stack_size, count * sizeof(*xsp)); xop->xo_stack_size = depth; xop->xo_stack = xsp; } return 0; } void xo_no_setlocale (void) { xo_locale_inited = 1; /* Skip initialization */ } /* * We need to decide if stdout is line buffered (_IOLBF). Lacking a * standard way to decide this (e.g. getlinebuf()), we have configure * look to find __flbf, which glibc supported. If not, we'll rely on * isatty, with the assumption that terminals are the only thing * that's line buffered. We _could_ test for "steam._flags & _IOLBF", * which is all __flbf does, but that's even tackier. Like a * bedazzled Elvis outfit on an ugly lap dog sort of tacky. Not * something we're willing to do. */ static int xo_is_line_buffered (FILE *stream) { #if HAVE___FLBF if (__flbf(stream)) return 1; #else /* HAVE___FLBF */ if (isatty(fileno(stream))) return 1; #endif /* HAVE___FLBF */ return 0; } /* * Initialize an xo_handle_t, using both static defaults and * the global settings from the LIBXO_OPTIONS environment * variable. */ static void xo_init_handle (xo_handle_t *xop) { xop->xo_opaque = stdout; xop->xo_write = xo_write_to_file; xop->xo_flush = xo_flush_file; if (xo_is_line_buffered(stdout)) XOF_SET(xop, XOF_FLUSH_LINE); /* * We need to initialize the locale, which isn't really pretty. * Libraries should depend on their caller to set up the * environment. But we really can't count on the caller to do * this, because well, they won't. Trust me. */ if (!xo_locale_inited) { xo_locale_inited = 1; /* Only do this once */ const char *cp = getenv("LC_CTYPE"); if (cp == NULL) cp = getenv("LANG"); if (cp == NULL) cp = getenv("LC_ALL"); if (cp == NULL) cp = "C"; /* Default for C programs */ (void) setlocale(LC_CTYPE, cp); } /* * Initialize only the xo_buffers we know we'll need; the others * can be allocated as needed. */ xo_buf_init(&xop->xo_data); xo_buf_init(&xop->xo_fmt); if (XOIF_ISSET(xop, XOIF_INIT_IN_PROGRESS)) return; XOIF_SET(xop, XOIF_INIT_IN_PROGRESS); xop->xo_indent_by = XO_INDENT_BY; xo_depth_check(xop, XO_DEPTH); XOIF_CLEAR(xop, XOIF_INIT_IN_PROGRESS); } /* * Initialize the default handle. */ static void xo_default_init (void) { xo_handle_t *xop = &xo_default_handle; xo_init_handle(xop); #if !defined(NO_LIBXO_OPTIONS) if (!XOF_ISSET(xop, XOF_NO_ENV)) { char *env = getenv("LIBXO_OPTIONS"); if (env) xo_set_options_simple(xop, env); } #endif /* NO_LIBXO_OPTIONS */ xo_default_inited = 1; } /* * Cheap convenience function to return either the argument, or * the internal handle, after it has been initialized. The usage * is: * xop = xo_default(xop); */ static xo_handle_t * xo_default (xo_handle_t *xop) { if (xop == NULL) { if (xo_default_inited == 0) xo_default_init(); xop = &xo_default_handle; } return xop; } /* * Return the number of spaces we should be indenting. If * we are pretty-printing, this is indent * indent_by. */ static int xo_indent (xo_handle_t *xop) { int rc = 0; xop = xo_default(xop); if (XOF_ISSET(xop, XOF_PRETTY)) { rc = xop->xo_indent * xop->xo_indent_by; if (XOIF_ISSET(xop, XOIF_TOP_EMITTED)) rc += xop->xo_indent_by; } return (rc > 0) ? rc : 0; } static void xo_buf_indent (xo_handle_t *xop, int indent) { xo_buffer_t *xbp = &xop->xo_data; if (indent <= 0) indent = xo_indent(xop); if (!xo_buf_has_room(xbp, indent)) return; memset(xbp->xb_curp, ' ', indent); xbp->xb_curp += indent; } static char xo_xml_amp[] = "&"; static char xo_xml_lt[] = "<"; static char xo_xml_gt[] = ">"; static char xo_xml_quot[] = """; static ssize_t xo_escape_xml (xo_buffer_t *xbp, ssize_t len, xo_xff_flags_t flags) { ssize_t slen; ssize_t delta = 0; char *cp, *ep, *ip; const char *sp; int attr = XOF_BIT_ISSET(flags, XFF_ATTR); for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) { /* We're subtracting 2: 1 for the NUL, 1 for the char we replace */ if (*cp == '<') delta += sizeof(xo_xml_lt) - 2; else if (*cp == '>') delta += sizeof(xo_xml_gt) - 2; else if (*cp == '&') delta += sizeof(xo_xml_amp) - 2; else if (attr && *cp == '"') delta += sizeof(xo_xml_quot) - 2; } if (delta == 0) /* Nothing to escape; bail */ return len; if (!xo_buf_has_room(xbp, delta)) /* No room; bail, but don't append */ return 0; ep = xbp->xb_curp; cp = ep + len; ip = cp + delta; do { cp -= 1; ip -= 1; if (*cp == '<') sp = xo_xml_lt; else if (*cp == '>') sp = xo_xml_gt; else if (*cp == '&') sp = xo_xml_amp; else if (attr && *cp == '"') sp = xo_xml_quot; else { *ip = *cp; continue; } slen = strlen(sp); ip -= slen - 1; memcpy(ip, sp, slen); } while (cp > ep && cp != ip); return len + delta; } static ssize_t xo_escape_json (xo_buffer_t *xbp, ssize_t len, xo_xff_flags_t flags UNUSED) { ssize_t delta = 0; char *cp, *ep, *ip; for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) { if (*cp == '\\' || *cp == '"') delta += 1; else if (*cp == '\n' || *cp == '\r') delta += 1; } if (delta == 0) /* Nothing to escape; bail */ return len; if (!xo_buf_has_room(xbp, delta)) /* No room; bail, but don't append */ return 0; ep = xbp->xb_curp; cp = ep + len; ip = cp + delta; do { cp -= 1; ip -= 1; if (*cp == '\\' || *cp == '"') { *ip-- = *cp; *ip = '\\'; } else if (*cp == '\n') { *ip-- = 'n'; *ip = '\\'; } else if (*cp == '\r') { *ip-- = 'r'; *ip = '\\'; } else { *ip = *cp; } } while (cp > ep && cp != ip); return len + delta; } /* * PARAM-VALUE = UTF-8-STRING ; characters '"', '\' and * ; ']' MUST be escaped. */ static ssize_t xo_escape_sdparams (xo_buffer_t *xbp, ssize_t len, xo_xff_flags_t flags UNUSED) { ssize_t delta = 0; char *cp, *ep, *ip; for (cp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) { if (*cp == '\\' || *cp == '"' || *cp == ']') delta += 1; } if (delta == 0) /* Nothing to escape; bail */ return len; if (!xo_buf_has_room(xbp, delta)) /* No room; bail, but don't append */ return 0; ep = xbp->xb_curp; cp = ep + len; ip = cp + delta; do { cp -= 1; ip -= 1; if (*cp == '\\' || *cp == '"' || *cp == ']') { *ip-- = *cp; *ip = '\\'; } else { *ip = *cp; } } while (cp > ep && cp != ip); return len + delta; } static void xo_buf_escape (xo_handle_t *xop, xo_buffer_t *xbp, const char *str, ssize_t len, xo_xff_flags_t flags) { if (!xo_buf_has_room(xbp, len)) return; memcpy(xbp->xb_curp, str, len); switch (xo_style(xop)) { case XO_STYLE_XML: case XO_STYLE_HTML: len = xo_escape_xml(xbp, len, flags); break; case XO_STYLE_JSON: len = xo_escape_json(xbp, len, flags); break; case XO_STYLE_SDPARAMS: len = xo_escape_sdparams(xbp, len, flags); break; } xbp->xb_curp += len; } /* * Write the current contents of the data buffer using the handle's * xo_write function. */ static ssize_t xo_write (xo_handle_t *xop) { ssize_t rc = 0; xo_buffer_t *xbp = &xop->xo_data; if (xbp->xb_curp != xbp->xb_bufp) { xo_buf_append(xbp, "", 1); /* Append ending NUL */ xo_anchor_clear(xop); if (xop->xo_write) rc = xop->xo_write(xop->xo_opaque, xbp->xb_bufp); xbp->xb_curp = xbp->xb_bufp; } /* Turn off the flags that don't survive across writes */ XOIF_CLEAR(xop, XOIF_UNITS_PENDING); return rc; } /* * Format arguments into our buffer. If a custom formatter has been set, * we use that to do the work; otherwise we vsnprintf(). */ static ssize_t xo_vsnprintf (xo_handle_t *xop, xo_buffer_t *xbp, const char *fmt, va_list vap) { va_list va_local; ssize_t rc; ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); va_copy(va_local, vap); if (xop->xo_formatter) rc = xop->xo_formatter(xop, xbp->xb_curp, left, fmt, va_local); else rc = vsnprintf(xbp->xb_curp, left, fmt, va_local); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { va_end(va_local); return -1; } /* * After we call vsnprintf(), the stage of vap is not defined. * We need to copy it before we pass. Then we have to do our * own logic below to move it along. This is because the * implementation can have va_list be a pointer (bsd) or a * structure (macosx) or anything in between. */ va_end(va_local); /* Reset vap to the start */ va_copy(va_local, vap); left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); if (xop->xo_formatter) rc = xop->xo_formatter(xop, xbp->xb_curp, left, fmt, va_local); else rc = vsnprintf(xbp->xb_curp, left, fmt, va_local); } va_end(va_local); return rc; } /* * Print some data through the handle. */ static ssize_t xo_printf_v (xo_handle_t *xop, const char *fmt, va_list vap) { xo_buffer_t *xbp = &xop->xo_data; ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); ssize_t rc; va_list va_local; va_copy(va_local, vap); rc = vsnprintf(xbp->xb_curp, left, fmt, va_local); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { va_end(va_local); return -1; } va_end(va_local); /* Reset vap to the start */ va_copy(va_local, vap); left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, va_local); } va_end(va_local); if (rc > 0) xbp->xb_curp += rc; return rc; } static ssize_t xo_printf (xo_handle_t *xop, const char *fmt, ...) { ssize_t rc; va_list vap; va_start(vap, fmt); rc = xo_printf_v(xop, fmt, vap); va_end(vap); return rc; } /* * These next few function are make The Essential UTF-8 Ginsu Knife. * Identify an input and output character, and convert it. */ static uint8_t xo_utf8_data_bits[5] = { 0, 0x7f, 0x1f, 0x0f, 0x07 }; static uint8_t xo_utf8_len_bits[5] = { 0, 0x00, 0xc0, 0xe0, 0xf0 }; /* * If the byte has a high-bit set, it's UTF-8, not ASCII. */ static int xo_is_utf8 (char ch) { return (ch & 0x80); } /* * Look at the high bits of the first byte to determine the length * of the UTF-8 character. */ static inline ssize_t xo_utf8_to_wc_len (const char *buf) { uint8_t bval = (uint8_t) *buf; ssize_t len; if ((bval & 0x80) == 0x0) len = 1; else if ((bval & 0xe0) == 0xc0) len = 2; else if ((bval & 0xf0) == 0xe0) len = 3; else if ((bval & 0xf8) == 0xf0) len = 4; else len = -1; return len; } static ssize_t xo_buf_utf8_len (xo_handle_t *xop, const char *buf, ssize_t bufsiz) { unsigned b = (unsigned char) *buf; ssize_t len, i; len = xo_utf8_to_wc_len(buf); if (len < 0) { xo_failure(xop, "invalid UTF-8 data: %02hhx", b); return -1; } if (len > bufsiz) { xo_failure(xop, "invalid UTF-8 data (short): %02hhx (%d/%d)", b, len, bufsiz); return -1; } for (i = 2; i < len; i++) { b = (unsigned char ) buf[i]; if ((b & 0xc0) != 0x80) { xo_failure(xop, "invalid UTF-8 data (byte %d): %x", i, b); return -1; } } return len; } /* * Build a wide character from the input buffer; the number of * bits we pull off the first character is dependent on the length, * but we put 6 bits off all other bytes. */ static inline wchar_t xo_utf8_char (const char *buf, ssize_t len) { /* Most common case: singleton byte */ if (len == 1) return (unsigned char) buf[0]; ssize_t i; wchar_t wc; const unsigned char *cp = (const unsigned char *) buf; wc = *cp & xo_utf8_data_bits[len]; for (i = 1; i < len; i++) { wc <<= 6; /* Low six bits have data */ wc |= cp[i] & 0x3f; if ((cp[i] & 0xc0) != 0x80) return (wchar_t) -1; } return wc; } /* * Determine the number of bytes needed to encode a wide character. */ static ssize_t xo_utf8_emit_len (wchar_t wc) { ssize_t len; if ((wc & ((1 << 7) - 1)) == wc) /* Simple case */ len = 1; else if ((wc & ((1 << 11) - 1)) == wc) len = 2; else if ((wc & ((1 << 16) - 1)) == wc) len = 3; else if ((wc & ((1 << 21) - 1)) == wc) len = 4; else len = -1; /* Invalid */ return len; } /* * Emit one wide character into the given buffer */ static void xo_utf8_emit_char (char *buf, ssize_t len, wchar_t wc) { ssize_t i; if (len == 1) { /* Simple case */ buf[0] = wc & 0x7f; return; } /* Start with the low bits and insert them, six bits at a time */ for (i = len - 1; i >= 0; i--) { buf[i] = 0x80 | (wc & 0x3f); wc >>= 6; /* Drop the low six bits */ } /* Finish off the first byte with the length bits */ buf[0] &= xo_utf8_data_bits[len]; /* Clear out the length bits */ buf[0] |= xo_utf8_len_bits[len]; /* Drop in new length bits */ } /* * Append a single UTF-8 character to a buffer, converting it to locale * encoding. Returns the number of columns consumed by that character, * as best we can determine it. */ static ssize_t xo_buf_append_locale_from_utf8 (xo_handle_t *xop, xo_buffer_t *xbp, const char *ibuf, ssize_t ilen) { wchar_t wc; ssize_t len; /* * Build our wide character from the input buffer; the number of * bits we pull off the first character is dependent on the length, * but we put 6 bits off all other bytes. */ wc = xo_utf8_char(ibuf, ilen); if (wc == (wchar_t) -1) { xo_failure(xop, "invalid UTF-8 byte sequence"); return 0; } if (XOF_ISSET(xop, XOF_NO_LOCALE)) { if (!xo_buf_has_room(xbp, ilen)) return 0; memcpy(xbp->xb_curp, ibuf, ilen); xbp->xb_curp += ilen; } else { if (!xo_buf_has_room(xbp, MB_LEN_MAX + 1)) return 0; bzero(&xop->xo_mbstate, sizeof(xop->xo_mbstate)); len = wcrtomb(xbp->xb_curp, wc, &xop->xo_mbstate); if (len <= 0) { xo_failure(xop, "could not convert wide char: %lx", (unsigned long) wc); return 0; } xbp->xb_curp += len; } return xo_wcwidth(wc); } /* * Append a UTF-8 string to a buffer, converting it into locale encoding */ static void xo_buf_append_locale (xo_handle_t *xop, xo_buffer_t *xbp, const char *cp, ssize_t len) { const char *sp = cp, *ep = cp + len; ssize_t save_off = xbp->xb_bufp - xbp->xb_curp; ssize_t slen; int cols = 0; for ( ; cp < ep; cp++) { if (!xo_is_utf8(*cp)) { cols += 1; continue; } /* * We're looking at a non-ascii UTF-8 character. * First we copy the previous data. * Then we need find the length and validate it. * Then we turn it into a wide string. * Then we turn it into a localized string. * Then we repeat. Isn't i18n fun? */ if (sp != cp) xo_buf_append(xbp, sp, cp - sp); /* Append previous data */ slen = xo_buf_utf8_len(xop, cp, ep - cp); if (slen <= 0) { /* Bad data; back it all out */ xbp->xb_curp = xbp->xb_bufp + save_off; return; } cols += xo_buf_append_locale_from_utf8(xop, xbp, cp, slen); /* Next time through, we'll start at the next character */ cp += slen - 1; sp = cp + 1; } /* Update column values */ if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += cols; /* Before we fall into the basic logic below, we need reset len */ len = ep - sp; if (len != 0) /* Append trailing data */ xo_buf_append(xbp, sp, len); } /* * Append the given string to the given buffer, without escaping or * character set conversion. This is the straight copy to the data * buffer with no fanciness. */ static void xo_data_append (xo_handle_t *xop, const char *str, ssize_t len) { xo_buf_append(&xop->xo_data, str, len); } /* * Append the given string to the given buffer */ static void xo_data_escape (xo_handle_t *xop, const char *str, ssize_t len) { xo_buf_escape(xop, &xop->xo_data, str, len, 0); } #ifdef LIBXO_NO_RETAIN /* * Empty implementations of the retain logic */ void xo_retain_clear_all (void) { return; } void xo_retain_clear (const char *fmt UNUSED) { return; } static void xo_retain_add (const char *fmt UNUSED, xo_field_info_t *fields UNUSED, unsigned num_fields UNUSED) { return; } static int xo_retain_find (const char *fmt UNUSED, xo_field_info_t **valp UNUSED, unsigned *nump UNUSED) { return -1; } #else /* !LIBXO_NO_RETAIN */ /* * Retain: We retain parsed field definitions to enhance performance, * especially inside loops. We depend on the caller treating the format * strings as immutable, so that we can retain pointers into them. We * hold the pointers in a hash table, so allow quick access. Retained * information is retained until xo_retain_clear is called. */ /* * xo_retain_entry_t holds information about one retained set of * parsed fields. */ typedef struct xo_retain_entry_s { struct xo_retain_entry_s *xre_next; /* Pointer to next (older) entry */ unsigned long xre_hits; /* Number of times we've hit */ const char *xre_format; /* Pointer to format string */ unsigned xre_num_fields; /* Number of fields saved */ xo_field_info_t *xre_fields; /* Pointer to fields */ } xo_retain_entry_t; /* * xo_retain_t holds a complete set of parsed fields as a hash table. */ #ifndef XO_RETAIN_SIZE #define XO_RETAIN_SIZE 6 #endif /* XO_RETAIN_SIZE */ #define RETAIN_HASH_SIZE (1<> 4) & (((1 << 24) - 1))); val = (val ^ 61) ^ (val >> 16); val = val + (val << 3); val = val ^ (val >> 4); val = val * 0x3a8f05c5; /* My large prime number */ val = val ^ (val >> 15); val &= RETAIN_HASH_SIZE - 1; return val; } /* * Walk all buckets, clearing all retained entries */ void xo_retain_clear_all (void) { int i; xo_retain_entry_t *xrep, *next; for (i = 0; i < RETAIN_HASH_SIZE; i++) { for (xrep = xo_retain.xr_bucket[i]; xrep; xrep = next) { next = xrep->xre_next; xo_free(xrep); } xo_retain.xr_bucket[i] = NULL; } xo_retain_count = 0; } /* * Walk all buckets, clearing all retained entries */ void xo_retain_clear (const char *fmt) { xo_retain_entry_t **xrepp; unsigned hash = xo_retain_hash(fmt); for (xrepp = &xo_retain.xr_bucket[hash]; *xrepp; xrepp = &(*xrepp)->xre_next) { if ((*xrepp)->xre_format == fmt) { *xrepp = (*xrepp)->xre_next; xo_retain_count -= 1; return; } } } /* * Search the hash for an entry matching 'fmt'; return it's fields. */ static int xo_retain_find (const char *fmt, xo_field_info_t **valp, unsigned *nump) { if (xo_retain_count == 0) return -1; unsigned hash = xo_retain_hash(fmt); xo_retain_entry_t *xrep; for (xrep = xo_retain.xr_bucket[hash]; xrep != NULL; xrep = xrep->xre_next) { if (xrep->xre_format == fmt) { *valp = xrep->xre_fields; *nump = xrep->xre_num_fields; xrep->xre_hits += 1; return 0; } } return -1; } static void xo_retain_add (const char *fmt, xo_field_info_t *fields, unsigned num_fields) { unsigned hash = xo_retain_hash(fmt); xo_retain_entry_t *xrep; ssize_t sz = sizeof(*xrep) + (num_fields + 1) * sizeof(*fields); xo_field_info_t *xfip; xrep = xo_realloc(NULL, sz); if (xrep == NULL) return; xfip = (xo_field_info_t *) &xrep[1]; memcpy(xfip, fields, num_fields * sizeof(*fields)); bzero(xrep, sizeof(*xrep)); xrep->xre_format = fmt; xrep->xre_fields = xfip; xrep->xre_num_fields = num_fields; /* Record the field info in the retain bucket */ xrep->xre_next = xo_retain.xr_bucket[hash]; xo_retain.xr_bucket[hash] = xrep; xo_retain_count += 1; } #endif /* !LIBXO_NO_RETAIN */ /* * Generate a warning. Normally, this is a text message written to * standard error. If the XOF_WARN_XML flag is set, then we generate * XMLified content on standard output. */ static void xo_warn_hcv (xo_handle_t *xop, int code, int check_warn, const char *fmt, va_list vap) { xop = xo_default(xop); if (check_warn && !XOF_ISSET(xop, XOF_WARN)) return; if (fmt == NULL) return; ssize_t len = strlen(fmt); ssize_t plen = xo_program ? strlen(xo_program) : 0; char *newfmt = alloca(len + 1 + plen + 2); /* NUL, and ": " */ if (plen) { memcpy(newfmt, xo_program, plen); newfmt[plen++] = ':'; newfmt[plen++] = ' '; } memcpy(newfmt + plen, fmt, len); newfmt[len + plen] = '\0'; if (XOF_ISSET(xop, XOF_WARN_XML)) { static char err_open[] = ""; static char err_close[] = ""; static char msg_open[] = ""; static char msg_close[] = ""; xo_buffer_t *xbp = &xop->xo_data; xo_buf_append(xbp, err_open, sizeof(err_open) - 1); xo_buf_append(xbp, msg_open, sizeof(msg_open) - 1); va_list va_local; va_copy(va_local, vap); ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); ssize_t rc = vsnprintf(xbp->xb_curp, left, newfmt, vap); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { va_end(va_local); return; } va_end(vap); /* Reset vap to the start */ va_copy(vap, va_local); left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, vap); } va_end(va_local); rc = xo_escape_xml(xbp, rc, 1); xbp->xb_curp += rc; xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1); xo_buf_append(xbp, err_close, sizeof(err_close) - 1); if (code >= 0) { const char *msg = strerror(code); if (msg) { xo_buf_append(xbp, ": ", 2); xo_buf_append(xbp, msg, strlen(msg)); } } xo_buf_append(xbp, "\n", 1); /* Append newline and NUL to string */ (void) xo_write(xop); } else { vfprintf(stderr, newfmt, vap); if (code >= 0) { const char *msg = strerror(code); if (msg) fprintf(stderr, ": %s", msg); } fprintf(stderr, "\n"); } } void xo_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_warn_hcv(xop, code, 0, fmt, vap); va_end(vap); } void xo_warn_c (int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, code, 0, fmt, vap); va_end(vap); } void xo_warn (const char *fmt, ...) { int code = errno; va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, code, 0, fmt, vap); va_end(vap); } void xo_warnx (const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, -1, 0, fmt, vap); va_end(vap); } void xo_err (int eval, const char *fmt, ...) { int code = errno; va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, code, 0, fmt, vap); va_end(vap); xo_finish(); exit(eval); } void xo_errx (int eval, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, -1, 0, fmt, vap); va_end(vap); xo_finish(); exit(eval); } void xo_errc (int eval, int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_warn_hcv(NULL, code, 0, fmt, vap); va_end(vap); xo_finish(); exit(eval); } /* * Generate a warning. Normally, this is a text message written to * standard error. If the XOF_WARN_XML flag is set, then we generate * XMLified content on standard output. */ void xo_message_hcv (xo_handle_t *xop, int code, const char *fmt, va_list vap) { static char msg_open[] = ""; static char msg_close[] = ""; xo_buffer_t *xbp; ssize_t rc; va_list va_local; xop = xo_default(xop); if (fmt == NULL || *fmt == '\0') return; int need_nl = (fmt[strlen(fmt) - 1] != '\n'); switch (xo_style(xop)) { case XO_STYLE_XML: xbp = &xop->xo_data; if (XOF_ISSET(xop, XOF_PRETTY)) xo_buf_indent(xop, xop->xo_indent_by); xo_buf_append(xbp, msg_open, sizeof(msg_open) - 1); va_copy(va_local, vap); ssize_t left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, vap); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) { va_end(va_local); return; } va_end(vap); /* Reset vap to the start */ va_copy(vap, va_local); left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = vsnprintf(xbp->xb_curp, left, fmt, vap); } va_end(va_local); rc = xo_escape_xml(xbp, rc, 0); xbp->xb_curp += rc; if (need_nl && code > 0) { const char *msg = strerror(code); if (msg) { xo_buf_append(xbp, ": ", 2); xo_buf_append(xbp, msg, strlen(msg)); } } if (need_nl) xo_buf_append(xbp, "\n", 1); /* Append newline and NUL to string */ xo_buf_append(xbp, msg_close, sizeof(msg_close) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_buf_append(xbp, "\n", 1); /* Append newline and NUL to string */ (void) xo_write(xop); break; case XO_STYLE_HTML: { char buf[BUFSIZ], *bp = buf, *cp; ssize_t bufsiz = sizeof(buf); ssize_t rc2; va_copy(va_local, vap); rc = vsnprintf(bp, bufsiz, fmt, va_local); if (rc > bufsiz) { bufsiz = rc + BUFSIZ; bp = alloca(bufsiz); va_end(va_local); va_copy(va_local, vap); rc = vsnprintf(bp, bufsiz, fmt, va_local); } va_end(va_local); cp = bp + rc; if (need_nl) { rc2 = snprintf(cp, bufsiz - rc, "%s%s\n", (code > 0) ? ": " : "", (code > 0) ? strerror(code) : ""); if (rc2 > 0) rc += rc2; } xo_buf_append_div(xop, "message", 0, NULL, 0, bp, rc, NULL, 0, NULL, 0); } break; case XO_STYLE_JSON: case XO_STYLE_SDPARAMS: case XO_STYLE_ENCODER: /* No means of representing messages */ return; case XO_STYLE_TEXT: rc = xo_printf_v(xop, fmt, vap); /* * XXX need to handle UTF-8 widths */ if (rc > 0) { if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += rc; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += rc; } if (need_nl && code > 0) { const char *msg = strerror(code); if (msg) { xo_printf(xop, ": %s", msg); } } if (need_nl) xo_printf(xop, "\n"); break; } switch (xo_style(xop)) { case XO_STYLE_HTML: if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) { static char div_close[] = "
"; XOIF_CLEAR(xop, XOIF_DIV_OPEN); xo_data_append(xop, div_close, sizeof(div_close) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); } break; } (void) xo_flush_h(xop); } void xo_message_hc (xo_handle_t *xop, int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_message_hcv(xop, code, fmt, vap); va_end(vap); } void xo_message_c (int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_message_hcv(NULL, code, fmt, vap); va_end(vap); } void xo_message_e (const char *fmt, ...) { int code = errno; va_list vap; va_start(vap, fmt); xo_message_hcv(NULL, code, fmt, vap); va_end(vap); } void xo_message (const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_message_hcv(NULL, 0, fmt, vap); va_end(vap); } static void xo_failure (xo_handle_t *xop, const char *fmt, ...) { if (!XOF_ISSET(xop, XOF_WARN)) return; va_list vap; va_start(vap, fmt); xo_warn_hcv(xop, -1, 1, fmt, vap); va_end(vap); } /** * Create a handle for use by later libxo functions. * * Note: normal use of libxo does not require a distinct handle, since * the default handle (used when NULL is passed) generates text on stdout. * * @param style Style of output desired (XO_STYLE_* value) * @param flags Set of XOF_* flags in use with this handle * @return Newly allocated handle * @see xo_destroy */ xo_handle_t * xo_create (xo_style_t style, xo_xof_flags_t flags) { xo_handle_t *xop = xo_realloc(NULL, sizeof(*xop)); if (xop) { bzero(xop, sizeof(*xop)); xop->xo_style = style; XOF_SET(xop, flags); xo_init_handle(xop); xop->xo_style = style; /* Reset style (see LIBXO_OPTIONS) */ } return xop; } /** * Create a handle that will write to the given file. Use * the XOF_CLOSE_FP flag to have the file closed on xo_destroy(). * * @param fp FILE pointer to use * @param style Style of output desired (XO_STYLE_* value) * @param flags Set of XOF_* flags to use with this handle * @return Newly allocated handle * @see xo_destroy */ xo_handle_t * xo_create_to_file (FILE *fp, xo_style_t style, xo_xof_flags_t flags) { xo_handle_t *xop = xo_create(style, flags); if (xop) { xop->xo_opaque = fp; xop->xo_write = xo_write_to_file; xop->xo_close = xo_close_file; xop->xo_flush = xo_flush_file; } return xop; } /** * Set the default handler to output to a file. * * @param xop libxo handle * @param fp FILE pointer to use * @return 0 on success, non-zero on failure */ int xo_set_file_h (xo_handle_t *xop, FILE *fp) { xop = xo_default(xop); if (fp == NULL) { xo_failure(xop, "xo_set_file: NULL fp"); return -1; } xop->xo_opaque = fp; xop->xo_write = xo_write_to_file; xop->xo_close = xo_close_file; xop->xo_flush = xo_flush_file; return 0; } /** * Set the default handler to output to a file. * * @param fp FILE pointer to use * @return 0 on success, non-zero on failure */ int xo_set_file (FILE *fp) { return xo_set_file_h(NULL, fp); } /** * Release any resources held by the handle. * * @param xop XO handle to alter (or NULL for default handle) */ void xo_destroy (xo_handle_t *xop_arg) { xo_handle_t *xop = xo_default(xop_arg); xo_flush_h(xop); if (xop->xo_close && XOF_ISSET(xop, XOF_CLOSE_FP)) xop->xo_close(xop->xo_opaque); xo_free(xop->xo_stack); xo_buf_cleanup(&xop->xo_data); xo_buf_cleanup(&xop->xo_fmt); xo_buf_cleanup(&xop->xo_predicate); xo_buf_cleanup(&xop->xo_attrs); xo_buf_cleanup(&xop->xo_color_buf); if (xop->xo_version) xo_free(xop->xo_version); if (xop_arg == NULL) { bzero(&xo_default_handle, sizeof(xo_default_handle)); xo_default_inited = 0; } else xo_free(xop); } /** * Record a new output style to use for the given handle (or default if * handle is NULL). This output style will be used for any future output. * * @param xop XO handle to alter (or NULL for default handle) * @param style new output style (XO_STYLE_*) */ void xo_set_style (xo_handle_t *xop, xo_style_t style) { xop = xo_default(xop); xop->xo_style = style; } /** * Return the current style of a handle * * @param xop XO handle to access * @return The handle's current style */ xo_style_t xo_get_style (xo_handle_t *xop) { xop = xo_default(xop); return xo_style(xop); } /** * Return the XO_STYLE_* value matching a given name * * @param name String name of a style * @return XO_STYLE_* value */ static int xo_name_to_style (const char *name) { if (strcmp(name, "xml") == 0) return XO_STYLE_XML; else if (strcmp(name, "json") == 0) return XO_STYLE_JSON; else if (strcmp(name, "encoder") == 0) return XO_STYLE_ENCODER; else if (strcmp(name, "text") == 0) return XO_STYLE_TEXT; else if (strcmp(name, "html") == 0) return XO_STYLE_HTML; else if (strcmp(name, "sdparams") == 0) return XO_STYLE_SDPARAMS; return -1; } /* * Indicate if the style is an "encoding" one as opposed to a "display" one. */ static int xo_style_is_encoding (xo_handle_t *xop) { if (xo_style(xop) == XO_STYLE_JSON || xo_style(xop) == XO_STYLE_XML || xo_style(xop) == XO_STYLE_SDPARAMS || xo_style(xop) == XO_STYLE_ENCODER) return 1; return 0; } /* Simple name-value mapping */ typedef struct xo_mapping_s { xo_xff_flags_t xm_value; /* Flag value */ const char *xm_name; /* String name */ } xo_mapping_t; static xo_xff_flags_t xo_name_lookup (xo_mapping_t *map, const char *value, ssize_t len) { if (len == 0) return 0; if (len < 0) len = strlen(value); while (isspace((int) *value)) { value += 1; len -= 1; } while (isspace((int) value[len])) len -= 1; if (*value == '\0') return 0; for ( ; map->xm_name; map++) if (strncmp(map->xm_name, value, len) == 0) return map->xm_value; return 0; } #ifdef NOT_NEEDED_YET static const char * xo_value_lookup (xo_mapping_t *map, xo_xff_flags_t value) { if (value == 0) return NULL; for ( ; map->xm_name; map++) if (map->xm_value == value) return map->xm_name; return NULL; } #endif /* NOT_NEEDED_YET */ static xo_mapping_t xo_xof_names[] = { { XOF_COLOR_ALLOWED, "color" }, { XOF_COLOR, "color-force" }, { XOF_COLUMNS, "columns" }, { XOF_DTRT, "dtrt" }, { XOF_FLUSH, "flush" }, { XOF_FLUSH_LINE, "flush-line" }, { XOF_IGNORE_CLOSE, "ignore-close" }, { XOF_INFO, "info" }, { XOF_KEYS, "keys" }, { XOF_LOG_GETTEXT, "log-gettext" }, { XOF_LOG_SYSLOG, "log-syslog" }, { XOF_NO_HUMANIZE, "no-humanize" }, { XOF_NO_LOCALE, "no-locale" }, { XOF_RETAIN_NONE, "no-retain" }, { XOF_NO_TOP, "no-top" }, { XOF_NOT_FIRST, "not-first" }, { XOF_PRETTY, "pretty" }, { XOF_RETAIN_ALL, "retain" }, { XOF_UNDERSCORES, "underscores" }, { XOF_UNITS, "units" }, { XOF_WARN, "warn" }, { XOF_WARN_XML, "warn-xml" }, { XOF_XPATH, "xpath" }, { 0, NULL } }; /* Options available via the environment variable ($LIBXO_OPTIONS) */ static xo_mapping_t xo_xof_simple_names[] = { { XOF_COLOR_ALLOWED, "color" }, { XOF_FLUSH, "flush" }, { XOF_FLUSH_LINE, "flush-line" }, { XOF_NO_HUMANIZE, "no-humanize" }, { XOF_NO_LOCALE, "no-locale" }, { XOF_RETAIN_NONE, "no-retain" }, { XOF_PRETTY, "pretty" }, { XOF_RETAIN_ALL, "retain" }, { XOF_UNDERSCORES, "underscores" }, { XOF_WARN, "warn" }, { 0, NULL } }; /* * Convert string name to XOF_* flag value. * Not all are useful. Or safe. Or sane. */ static unsigned xo_name_to_flag (const char *name) { return (unsigned) xo_name_lookup(xo_xof_names, name, -1); } /** * Set the style of an libxo handle based on a string name * * @param xop XO handle * @param name String value of name * @return 0 on success, non-zero on failure */ int xo_set_style_name (xo_handle_t *xop, const char *name) { if (name == NULL) return -1; int style = xo_name_to_style(name); if (style < 0) return -1; xo_set_style(xop, style); return 0; } /* * Fill in the color map, based on the input string; currently unimplemented * Look for something like "colors=red/blue+green/yellow" as fg/bg pairs. */ static void xo_set_color_map (xo_handle_t *xop, char *value) { #ifdef LIBXO_TEXT_ONLY return; #endif /* LIBXO_TEXT_ONLY */ char *cp, *ep, *vp, *np; ssize_t len = value ? strlen(value) + 1 : 0; int num = 1, fg, bg; for (cp = value, ep = cp + len - 1; cp && *cp && cp < ep; cp = np) { np = strchr(cp, '+'); if (np) *np++ = '\0'; vp = strchr(cp, '/'); if (vp) *vp++ = '\0'; fg = *cp ? xo_color_find(cp) : -1; bg = (vp && *vp) ? xo_color_find(vp) : -1; xop->xo_color_map_fg[num] = (fg < 0) ? num : fg; xop->xo_color_map_bg[num] = (bg < 0) ? num : bg; if (++num > XO_NUM_COLORS) break; } /* If no color initialization happened, then we don't need the map */ if (num > 0) XOF_SET(xop, XOF_COLOR_MAP); else XOF_CLEAR(xop, XOF_COLOR_MAP); /* Fill in the rest of the colors with the defaults */ for ( ; num < XO_NUM_COLORS; num++) xop->xo_color_map_fg[num] = xop->xo_color_map_bg[num] = num; } static int xo_set_options_simple (xo_handle_t *xop, const char *input) { xo_xof_flags_t new_flag; char *cp, *ep, *vp, *np, *bp; ssize_t len = strlen(input) + 1; bp = alloca(len); memcpy(bp, input, len); for (cp = bp, ep = cp + len - 1; cp && cp < ep; cp = np) { np = strchr(cp, ','); if (np) *np++ = '\0'; vp = strchr(cp, '='); if (vp) *vp++ = '\0'; if (strcmp("colors", cp) == 0) { xo_set_color_map(xop, vp); continue; } new_flag = xo_name_lookup(xo_xof_simple_names, cp, -1); if (new_flag != 0) { XOF_SET(xop, new_flag); } else if (strcmp(cp, "no-color") == 0) { XOF_CLEAR(xop, XOF_COLOR_ALLOWED); } else { xo_failure(xop, "unknown simple option: %s", cp); return -1; } } return 0; } /** * Set the options for a handle using a string of options * passed in. The input is a comma-separated set of names * and optional values: "xml,pretty,indent=4" * * @param xop XO handle * @param input Comma-separated set of option values * @return 0 on success, non-zero on failure */ int xo_set_options (xo_handle_t *xop, const char *input) { char *cp, *ep, *vp, *np, *bp; int style = -1, new_style, rc = 0; ssize_t len; xo_xof_flags_t new_flag; if (input == NULL) return 0; xop = xo_default(xop); #ifdef LIBXO_COLOR_ON_BY_DEFAULT /* If the installer used --enable-color-on-by-default, then we allow it */ XOF_SET(xop, XOF_COLOR_ALLOWED); #endif /* LIBXO_COLOR_ON_BY_DEFAULT */ /* * We support a simpler, old-school style of giving option * also, using a single character for each option. It's * ideal for lazy people, such as myself. */ if (*input == ':') { ssize_t sz; for (input++ ; *input; input++) { switch (*input) { case 'c': XOF_SET(xop, XOF_COLOR_ALLOWED); break; case 'f': XOF_SET(xop, XOF_FLUSH); break; case 'F': XOF_SET(xop, XOF_FLUSH_LINE); break; case 'g': XOF_SET(xop, XOF_LOG_GETTEXT); break; case 'H': xop->xo_style = XO_STYLE_HTML; break; case 'I': XOF_SET(xop, XOF_INFO); break; case 'i': sz = strspn(input + 1, "0123456789"); if (sz > 0) { xop->xo_indent_by = atoi(input + 1); input += sz - 1; /* Skip value */ } break; case 'J': xop->xo_style = XO_STYLE_JSON; break; case 'k': XOF_SET(xop, XOF_KEYS); break; case 'n': XOF_SET(xop, XOF_NO_HUMANIZE); break; case 'P': XOF_SET(xop, XOF_PRETTY); break; case 'T': xop->xo_style = XO_STYLE_TEXT; break; case 'U': XOF_SET(xop, XOF_UNITS); break; case 'u': XOF_SET(xop, XOF_UNDERSCORES); break; case 'W': XOF_SET(xop, XOF_WARN); break; case 'X': xop->xo_style = XO_STYLE_XML; break; case 'x': XOF_SET(xop, XOF_XPATH); break; } } return 0; } len = strlen(input) + 1; bp = alloca(len); memcpy(bp, input, len); for (cp = bp, ep = cp + len - 1; cp && cp < ep; cp = np) { np = strchr(cp, ','); if (np) *np++ = '\0'; vp = strchr(cp, '='); if (vp) *vp++ = '\0'; if (strcmp("colors", cp) == 0) { xo_set_color_map(xop, vp); continue; } /* * For options, we don't allow "encoder" since we want to * handle it explicitly below as "encoder=xxx". */ new_style = xo_name_to_style(cp); if (new_style >= 0 && new_style != XO_STYLE_ENCODER) { if (style >= 0) xo_warnx("ignoring multiple styles: '%s'", cp); else style = new_style; } else { new_flag = xo_name_to_flag(cp); if (new_flag != 0) XOF_SET(xop, new_flag); else if (strcmp(cp, "no-color") == 0) XOF_CLEAR(xop, XOF_COLOR_ALLOWED); else if (strcmp(cp, "indent") == 0) { if (vp) xop->xo_indent_by = atoi(vp); else xo_failure(xop, "missing value for indent option"); } else if (strcmp(cp, "encoder") == 0) { if (vp == NULL) xo_failure(xop, "missing value for encoder option"); else { if (xo_encoder_init(xop, vp)) { xo_failure(xop, "encoder not found: %s", vp); rc = -1; } } } else { xo_warnx("unknown libxo option value: '%s'", cp); rc = -1; } } } if (style > 0) xop->xo_style= style; return rc; } /** * Set one or more flags for a given handle (or default if handle is NULL). * These flags will affect future output. * * @param xop XO handle to alter (or NULL for default handle) * @param flags Flags to be set (XOF_*) */ void xo_set_flags (xo_handle_t *xop, xo_xof_flags_t flags) { xop = xo_default(xop); XOF_SET(xop, flags); } /** * Accessor to return the current set of flags for a handle * @param xop XO handle * @return Current set of flags */ xo_xof_flags_t xo_get_flags (xo_handle_t *xop) { xop = xo_default(xop); return xop->xo_flags; } /** * strndup with a twist: len < 0 means len = strlen(str) */ static char * xo_strndup (const char *str, ssize_t len) { if (len < 0) len = strlen(str); char *cp = xo_realloc(NULL, len + 1); if (cp) { memcpy(cp, str, len); cp[len] = '\0'; } return cp; } /** * Record a leading prefix for the XPath we generate. This allows the * generated data to be placed within an XML hierarchy but still have * accurate XPath expressions. * * @param xop XO handle to alter (or NULL for default handle) * @param path The XPath expression */ void xo_set_leading_xpath (xo_handle_t *xop, const char *path) { xop = xo_default(xop); if (xop->xo_leading_xpath) { xo_free(xop->xo_leading_xpath); xop->xo_leading_xpath = NULL; } if (path == NULL) return; xop->xo_leading_xpath = xo_strndup(path, -1); } /** * Record the info data for a set of tags * * @param xop XO handle to alter (or NULL for default handle) * @param info Info data (xo_info_t) to be recorded (or NULL) (MUST BE SORTED) * @pararm count Number of entries in info (or -1 to count them ourselves) */ void xo_set_info (xo_handle_t *xop, xo_info_t *infop, int count) { xop = xo_default(xop); if (count < 0 && infop) { xo_info_t *xip; for (xip = infop, count = 0; xip->xi_name; xip++, count++) continue; } xop->xo_info = infop; xop->xo_info_count = count; } /** * Set the formatter callback for a handle. The callback should * return a newly formatting contents of a formatting instruction, * meaning the bits inside the braces. */ void xo_set_formatter (xo_handle_t *xop, xo_formatter_t func, xo_checkpointer_t cfunc) { xop = xo_default(xop); xop->xo_formatter = func; xop->xo_checkpointer = cfunc; } /** * Clear one or more flags for a given handle (or default if handle is NULL). * These flags will affect future output. * * @param xop XO handle to alter (or NULL for default handle) * @param flags Flags to be cleared (XOF_*) */ void xo_clear_flags (xo_handle_t *xop, xo_xof_flags_t flags) { xop = xo_default(xop); XOF_CLEAR(xop, flags); } static const char * xo_state_name (xo_state_t state) { static const char *names[] = { "init", "open_container", "close_container", "open_list", "close_list", "open_instance", "close_instance", "open_leaf_list", "close_leaf_list", "discarding", "marker", "emit", "emit_leaf_list", "finish", NULL }; if (state < (sizeof(names) / sizeof(names[0]))) return names[state]; return "unknown"; } static void xo_line_ensure_open (xo_handle_t *xop, xo_xff_flags_t flags UNUSED) { static char div_open[] = "
"; static char div_open_blank[] = "
"; if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) return; if (xo_style(xop) != XO_STYLE_HTML) return; XOIF_SET(xop, XOIF_DIV_OPEN); if (flags & XFF_BLANK_LINE) xo_data_append(xop, div_open_blank, sizeof(div_open_blank) - 1); else xo_data_append(xop, div_open, sizeof(div_open) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); } static void xo_line_close (xo_handle_t *xop) { static char div_close[] = "
"; switch (xo_style(xop)) { case XO_STYLE_HTML: if (!XOIF_ISSET(xop, XOIF_DIV_OPEN)) xo_line_ensure_open(xop, 0); XOIF_CLEAR(xop, XOIF_DIV_OPEN); xo_data_append(xop, div_close, sizeof(div_close) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); break; case XO_STYLE_TEXT: xo_data_append(xop, "\n", 1); break; } } static int xo_info_compare (const void *key, const void *data) { const char *name = key; const xo_info_t *xip = data; return strcmp(name, xip->xi_name); } static xo_info_t * xo_info_find (xo_handle_t *xop, const char *name, ssize_t nlen) { xo_info_t *xip; char *cp = alloca(nlen + 1); /* Need local copy for NUL termination */ memcpy(cp, name, nlen); cp[nlen] = '\0'; xip = bsearch(cp, xop->xo_info, xop->xo_info_count, sizeof(xop->xo_info[0]), xo_info_compare); return xip; } #define CONVERT(_have, _need) (((_have) << 8) | (_need)) /* * Check to see that the conversion is safe and sane. */ static int xo_check_conversion (xo_handle_t *xop, int have_enc, int need_enc) { switch (CONVERT(have_enc, need_enc)) { case CONVERT(XF_ENC_UTF8, XF_ENC_UTF8): case CONVERT(XF_ENC_UTF8, XF_ENC_LOCALE): case CONVERT(XF_ENC_WIDE, XF_ENC_UTF8): case CONVERT(XF_ENC_WIDE, XF_ENC_LOCALE): case CONVERT(XF_ENC_LOCALE, XF_ENC_LOCALE): case CONVERT(XF_ENC_LOCALE, XF_ENC_UTF8): return 0; default: xo_failure(xop, "invalid conversion (%c:%c)", have_enc, need_enc); return 1; } } static int xo_format_string_direct (xo_handle_t *xop, xo_buffer_t *xbp, xo_xff_flags_t flags, const wchar_t *wcp, const char *cp, ssize_t len, int max, int need_enc, int have_enc) { int cols = 0; wchar_t wc = 0; ssize_t ilen, olen; ssize_t width; int attr = XOF_BIT_ISSET(flags, XFF_ATTR); const char *sp; if (len > 0 && !xo_buf_has_room(xbp, len)) return 0; for (;;) { if (len == 0) break; if (cp) { if (*cp == '\0') break; if ((flags & XFF_UNESCAPE) && (*cp == '\\' || *cp == '%')) { cp += 1; len -= 1; if (len == 0 || *cp == '\0') break; } } if (wcp && *wcp == L'\0') break; ilen = 0; switch (have_enc) { case XF_ENC_WIDE: /* Wide character */ wc = *wcp++; ilen = 1; break; case XF_ENC_UTF8: /* UTF-8 */ ilen = xo_utf8_to_wc_len(cp); if (ilen < 0) { xo_failure(xop, "invalid UTF-8 character: %02hhx", *cp); return -1; /* Can't continue; we can't find the end */ } if (len > 0 && len < ilen) { len = 0; /* Break out of the loop */ continue; } wc = xo_utf8_char(cp, ilen); if (wc == (wchar_t) -1) { xo_failure(xop, "invalid UTF-8 character: %02hhx/%d", *cp, ilen); return -1; /* Can't continue; we can't find the end */ } cp += ilen; break; case XF_ENC_LOCALE: /* Native locale */ ilen = (len > 0) ? len : MB_LEN_MAX; ilen = mbrtowc(&wc, cp, ilen, &xop->xo_mbstate); if (ilen < 0) { /* Invalid data; skip */ xo_failure(xop, "invalid mbs char: %02hhx", *cp); wc = L'?'; ilen = 1; } if (ilen == 0) { /* Hit a wide NUL character */ len = 0; continue; } cp += ilen; break; } /* Reduce len, but not below zero */ if (len > 0) { len -= ilen; if (len < 0) len = 0; } /* * Find the width-in-columns of this character, which must be done * in wide characters, since we lack a mbswidth() function. If * it doesn't fit */ width = xo_wcwidth(wc); if (width < 0) width = iswcntrl(wc) ? 0 : 1; if (xo_style(xop) == XO_STYLE_TEXT || xo_style(xop) == XO_STYLE_HTML) { if (max > 0 && cols + width > max) break; } switch (need_enc) { case XF_ENC_UTF8: /* Output in UTF-8 needs to be escaped, based on the style */ switch (xo_style(xop)) { case XO_STYLE_XML: case XO_STYLE_HTML: if (wc == '<') sp = xo_xml_lt; else if (wc == '>') sp = xo_xml_gt; else if (wc == '&') sp = xo_xml_amp; else if (attr && wc == '"') sp = xo_xml_quot; else break; ssize_t slen = strlen(sp); if (!xo_buf_has_room(xbp, slen - 1)) return -1; memcpy(xbp->xb_curp, sp, slen); xbp->xb_curp += slen; goto done_with_encoding; /* Need multi-level 'break' */ case XO_STYLE_JSON: if (wc != '\\' && wc != '"' && wc != '\n' && wc != '\r') break; if (!xo_buf_has_room(xbp, 2)) return -1; *xbp->xb_curp++ = '\\'; if (wc == '\n') wc = 'n'; else if (wc == '\r') wc = 'r'; else wc = wc & 0x7f; *xbp->xb_curp++ = wc; goto done_with_encoding; case XO_STYLE_SDPARAMS: if (wc != '\\' && wc != '"' && wc != ']') break; if (!xo_buf_has_room(xbp, 2)) return -1; *xbp->xb_curp++ = '\\'; wc = wc & 0x7f; *xbp->xb_curp++ = wc; goto done_with_encoding; } olen = xo_utf8_emit_len(wc); if (olen < 0) { xo_failure(xop, "ignoring bad length"); continue; } if (!xo_buf_has_room(xbp, olen)) return -1; xo_utf8_emit_char(xbp->xb_curp, olen, wc); xbp->xb_curp += olen; break; case XF_ENC_LOCALE: if (!xo_buf_has_room(xbp, MB_LEN_MAX + 1)) return -1; olen = wcrtomb(xbp->xb_curp, wc, &xop->xo_mbstate); if (olen <= 0) { xo_failure(xop, "could not convert wide char: %lx", (unsigned long) wc); width = 1; *xbp->xb_curp++ = '?'; } else xbp->xb_curp += olen; break; } done_with_encoding: cols += width; } return cols; } static int xo_needed_encoding (xo_handle_t *xop) { if (XOF_ISSET(xop, XOF_UTF8)) /* Check the override flag */ return XF_ENC_UTF8; if (xo_style(xop) == XO_STYLE_TEXT) /* Text means locale */ return XF_ENC_LOCALE; return XF_ENC_UTF8; /* Otherwise, we love UTF-8 */ } static ssize_t xo_format_string (xo_handle_t *xop, xo_buffer_t *xbp, xo_xff_flags_t flags, xo_format_t *xfp) { static char null[] = "(null)"; static char null_no_quotes[] = "null"; char *cp = NULL; wchar_t *wcp = NULL; ssize_t len; ssize_t cols = 0, rc = 0; ssize_t off = xbp->xb_curp - xbp->xb_bufp, off2; int need_enc = xo_needed_encoding(xop); if (xo_check_conversion(xop, xfp->xf_enc, need_enc)) return 0; len = xfp->xf_width[XF_WIDTH_SIZE]; if (xfp->xf_fc == 'm') { cp = strerror(xop->xo_errno); if (len < 0) len = cp ? strlen(cp) : 0; goto normal_string; } else if (xfp->xf_enc == XF_ENC_WIDE) { wcp = va_arg(xop->xo_vap, wchar_t *); if (xfp->xf_skip) return 0; /* * Dont' deref NULL; use the traditional "(null)" instead * of the more accurate "who's been a naughty boy, then?". */ if (wcp == NULL) { cp = null; len = sizeof(null) - 1; } } else { cp = va_arg(xop->xo_vap, char *); /* UTF-8 or native */ normal_string: if (xfp->xf_skip) return 0; /* Echo "Dont' deref NULL" logic */ if (cp == NULL) { if ((flags & XFF_NOQUOTE) && xo_style_is_encoding(xop)) { cp = null_no_quotes; len = sizeof(null_no_quotes) - 1; } else { cp = null; len = sizeof(null) - 1; } } /* * Optimize the most common case, which is "%s". We just * need to copy the complete string to the output buffer. */ if (xfp->xf_enc == need_enc && xfp->xf_width[XF_WIDTH_MIN] < 0 && xfp->xf_width[XF_WIDTH_SIZE] < 0 && xfp->xf_width[XF_WIDTH_MAX] < 0 && !(XOIF_ISSET(xop, XOIF_ANCHOR) || XOF_ISSET(xop, XOF_COLUMNS))) { len = strlen(cp); xo_buf_escape(xop, xbp, cp, len, flags); /* * Our caller expects xb_curp left untouched, so we have * to reset it and return the number of bytes written to * the buffer. */ off2 = xbp->xb_curp - xbp->xb_bufp; rc = off2 - off; xbp->xb_curp = xbp->xb_bufp + off; return rc; } } cols = xo_format_string_direct(xop, xbp, flags, wcp, cp, len, xfp->xf_width[XF_WIDTH_MAX], need_enc, xfp->xf_enc); if (cols < 0) goto bail; /* * xo_buf_append* will move xb_curp, so we save/restore it. */ off2 = xbp->xb_curp - xbp->xb_bufp; rc = off2 - off; xbp->xb_curp = xbp->xb_bufp + off; if (cols < xfp->xf_width[XF_WIDTH_MIN]) { /* * Find the number of columns needed to display the string. * If we have the original wide string, we just call wcswidth, * but if we did the work ourselves, then we need to do it. */ int delta = xfp->xf_width[XF_WIDTH_MIN] - cols; if (!xo_buf_has_room(xbp, xfp->xf_width[XF_WIDTH_MIN])) goto bail; /* * If seen_minus, then pad on the right; otherwise move it so * we can pad on the left. */ if (xfp->xf_seen_minus) { cp = xbp->xb_curp + rc; } else { cp = xbp->xb_curp; memmove(xbp->xb_curp + delta, xbp->xb_curp, rc); } /* Set the padding */ memset(cp, (xfp->xf_leading_zero > 0) ? '0' : ' ', delta); rc += delta; cols += delta; } if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += cols; return rc; bail: xbp->xb_curp = xbp->xb_bufp + off; return 0; } /* * Look backwards in a buffer to find a numeric value */ static int xo_buf_find_last_number (xo_buffer_t *xbp, ssize_t start_offset) { int rc = 0; /* Fail with zero */ int digit = 1; char *sp = xbp->xb_bufp; char *cp = sp + start_offset; while (--cp >= sp) if (isdigit((int) *cp)) break; for ( ; cp >= sp; cp--) { if (!isdigit((int) *cp)) break; rc += (*cp - '0') * digit; digit *= 10; } return rc; } static ssize_t xo_count_utf8_cols (const char *str, ssize_t len) { ssize_t tlen; wchar_t wc; ssize_t cols = 0; const char *ep = str + len; while (str < ep) { tlen = xo_utf8_to_wc_len(str); if (tlen < 0) /* Broken input is very bad */ return cols; wc = xo_utf8_char(str, tlen); if (wc == (wchar_t) -1) return cols; /* We only print printable characters */ if (iswprint((wint_t) wc)) { /* * Find the width-in-columns of this character, which must be done * in wide characters, since we lack a mbswidth() function. */ ssize_t width = xo_wcwidth(wc); if (width < 0) width = iswcntrl(wc) ? 0 : 1; cols += width; } str += tlen; } return cols; } #ifdef HAVE_GETTEXT static inline const char * xo_dgettext (xo_handle_t *xop, const char *str) { const char *domainname = xop->xo_gt_domain; const char *res; res = dgettext(domainname, str); if (XOF_ISSET(xop, XOF_LOG_GETTEXT)) fprintf(stderr, "xo: gettext: %s%s%smsgid \"%s\" returns \"%s\"\n", domainname ? "domain \"" : "", xo_printable(domainname), domainname ? "\", " : "", xo_printable(str), xo_printable(res)); return res; } static inline const char * xo_dngettext (xo_handle_t *xop, const char *sing, const char *plural, unsigned long int n) { const char *domainname = xop->xo_gt_domain; const char *res; res = dngettext(domainname, sing, plural, n); if (XOF_ISSET(xop, XOF_LOG_GETTEXT)) fprintf(stderr, "xo: gettext: %s%s%s" "msgid \"%s\", msgid_plural \"%s\" (%lu) returns \"%s\"\n", domainname ? "domain \"" : "", xo_printable(domainname), domainname ? "\", " : "", xo_printable(sing), xo_printable(plural), n, xo_printable(res)); return res; } #else /* HAVE_GETTEXT */ static inline const char * xo_dgettext (xo_handle_t *xop UNUSED, const char *str) { return str; } static inline const char * xo_dngettext (xo_handle_t *xop UNUSED, const char *singular, const char *plural, unsigned long int n) { return (n == 1) ? singular : plural; } #endif /* HAVE_GETTEXT */ /* * This is really _re_formatting, since the normal format code has * generated a beautiful string into xo_data, starting at * start_offset. We need to see if it's plural, which means * comma-separated options, or singular. Then we make the appropriate * call to d[n]gettext() to get the locale-based version. Note that * both input and output of gettext() this should be UTF-8. */ static ssize_t xo_format_gettext (xo_handle_t *xop, xo_xff_flags_t flags, ssize_t start_offset, ssize_t cols, int need_enc) { xo_buffer_t *xbp = &xop->xo_data; if (!xo_buf_has_room(xbp, 1)) return cols; xbp->xb_curp[0] = '\0'; /* NUL-terminate the input string */ char *cp = xbp->xb_bufp + start_offset; ssize_t len = xbp->xb_curp - cp; const char *newstr = NULL; /* * The plural flag asks us to look backwards at the last numeric * value rendered and disect the string into two pieces. */ if (flags & XFF_GT_PLURAL) { int n = xo_buf_find_last_number(xbp, start_offset); char *two = memchr(cp, (int) ',', len); if (two == NULL) { xo_failure(xop, "no comma in plural gettext field: '%s'", cp); return cols; } if (two == cp) { xo_failure(xop, "nothing before comma in plural gettext " "field: '%s'", cp); return cols; } if (two == xbp->xb_curp) { xo_failure(xop, "nothing after comma in plural gettext " "field: '%s'", cp); return cols; } *two++ = '\0'; if (flags & XFF_GT_FIELD) { newstr = xo_dngettext(xop, cp, two, n); } else { /* Don't do a gettext() look up, just get the plural form */ newstr = (n == 1) ? cp : two; } /* * If we returned the first string, optimize a bit by * backing up over comma */ if (newstr == cp) { xbp->xb_curp = two - 1; /* One for comma */ /* * If the caller wanted UTF8, we're done; nothing changed, * but we need to count the columns used. */ if (need_enc == XF_ENC_UTF8) return xo_count_utf8_cols(cp, xbp->xb_curp - cp); } } else { /* The simple case (singular) */ newstr = xo_dgettext(xop, cp); if (newstr == cp) { /* If the caller wanted UTF8, we're done; nothing changed */ if (need_enc == XF_ENC_UTF8) return cols; } } /* * Since the new string string might be in gettext's buffer or * in the buffer (as the plural form), we make a copy. */ ssize_t nlen = strlen(newstr); char *newcopy = alloca(nlen + 1); memcpy(newcopy, newstr, nlen + 1); xbp->xb_curp = xbp->xb_bufp + start_offset; /* Reset the buffer */ return xo_format_string_direct(xop, xbp, flags, NULL, newcopy, nlen, 0, need_enc, XF_ENC_UTF8); } static void xo_data_append_content (xo_handle_t *xop, const char *str, ssize_t len, xo_xff_flags_t flags) { int cols; int need_enc = xo_needed_encoding(xop); ssize_t start_offset = xo_buf_offset(&xop->xo_data); cols = xo_format_string_direct(xop, &xop->xo_data, XFF_UNESCAPE | flags, NULL, str, len, -1, need_enc, XF_ENC_UTF8); if (flags & XFF_GT_FLAGS) cols = xo_format_gettext(xop, flags, start_offset, cols, need_enc); if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += cols; } /** * Bump one of the 'width' values in a format strings (e.g. "%40.50.60s"). * @param xfp Formatting instructions * @param digit Single digit (0-9) of input */ static void xo_bump_width (xo_format_t *xfp, int digit) { int *ip = &xfp->xf_width[xfp->xf_dots]; *ip = ((*ip > 0) ? *ip : 0) * 10 + digit; } static ssize_t xo_trim_ws (xo_buffer_t *xbp, ssize_t len) { char *cp, *sp, *ep; ssize_t delta; /* First trim leading space */ for (cp = sp = xbp->xb_curp, ep = cp + len; cp < ep; cp++) { if (*cp != ' ') break; } delta = cp - sp; if (delta) { len -= delta; memmove(sp, cp, len); } /* Then trim off the end */ for (cp = xbp->xb_curp, sp = ep = cp + len; cp < ep; ep--) { if (ep[-1] != ' ') break; } delta = sp - ep; if (delta) { len -= delta; cp[len] = '\0'; } return len; } /* * Interface to format a single field. The arguments are in xo_vap, * and the format is in 'fmt'. If 'xbp' is null, we use xop->xo_data; * this is the most common case. */ static ssize_t xo_do_format_field (xo_handle_t *xop, xo_buffer_t *xbp, const char *fmt, ssize_t flen, xo_xff_flags_t flags) { xo_format_t xf; const char *cp, *ep, *sp, *xp = NULL; ssize_t rc, cols; int style = (flags & XFF_XML) ? XO_STYLE_XML : xo_style(xop); unsigned make_output = !(flags & XFF_NO_OUTPUT) ? 1 : 0; int need_enc = xo_needed_encoding(xop); int real_need_enc = need_enc; ssize_t old_cols = xop->xo_columns; /* The gettext interface is UTF-8, so we'll need that for now */ if (flags & XFF_GT_FIELD) need_enc = XF_ENC_UTF8; if (xbp == NULL) xbp = &xop->xo_data; ssize_t start_offset = xo_buf_offset(xbp); for (cp = fmt, ep = fmt + flen; cp < ep; cp++) { /* * Since we're starting a new field, save the starting offset. * We'll need this later for field-related operations. */ if (*cp != '%') { add_one: if (xp == NULL) xp = cp; if (*cp == '\\' && cp[1] != '\0') cp += 1; continue; } if (cp + 1 < ep && cp[1] == '%') { cp += 1; goto add_one; } if (xp) { if (make_output) { cols = xo_format_string_direct(xop, xbp, flags | XFF_UNESCAPE, NULL, xp, cp - xp, -1, need_enc, XF_ENC_UTF8); if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += cols; } xp = NULL; } bzero(&xf, sizeof(xf)); xf.xf_leading_zero = -1; xf.xf_width[0] = xf.xf_width[1] = xf.xf_width[2] = -1; /* * "%@" starts an XO-specific set of flags: * @X@ - XML-only field; ignored if style isn't XML */ if (cp[1] == '@') { for (cp += 2; cp < ep; cp++) { if (*cp == '@') { break; } if (*cp == '*') { /* * '*' means there's a "%*.*s" value in vap that * we want to ignore */ if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) va_arg(xop->xo_vap, int); } } } /* Hidden fields are only visible to JSON and XML */ if (XOF_ISSET(xop, XFF_ENCODE_ONLY)) { if (style != XO_STYLE_XML && !xo_style_is_encoding(xop)) xf.xf_skip = 1; } else if (XOF_ISSET(xop, XFF_DISPLAY_ONLY)) { if (style != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) xf.xf_skip = 1; } if (!make_output) xf.xf_skip = 1; /* * Looking at one piece of a format; find the end and * call snprintf. Then advance xo_vap on our own. * * Note that 'n', 'v', and '$' are not supported. */ sp = cp; /* Save start pointer */ for (cp += 1; cp < ep; cp++) { if (*cp == 'l') xf.xf_lflag += 1; else if (*cp == 'h') xf.xf_hflag += 1; else if (*cp == 'j') xf.xf_jflag += 1; else if (*cp == 't') xf.xf_tflag += 1; else if (*cp == 'z') xf.xf_zflag += 1; else if (*cp == 'q') xf.xf_qflag += 1; else if (*cp == '.') { if (++xf.xf_dots >= XF_WIDTH_NUM) { xo_failure(xop, "Too many dots in format: '%s'", fmt); return -1; } } else if (*cp == '-') xf.xf_seen_minus = 1; else if (isdigit((int) *cp)) { if (xf.xf_leading_zero < 0) xf.xf_leading_zero = (*cp == '0'); xo_bump_width(&xf, *cp - '0'); } else if (*cp == '*') { xf.xf_stars += 1; xf.xf_star[xf.xf_dots] = 1; } else if (strchr("diouxXDOUeEfFgGaAcCsSpm", *cp) != NULL) break; else if (*cp == 'n' || *cp == 'v') { xo_failure(xop, "unsupported format: '%s'", fmt); return -1; } } if (cp == ep) xo_failure(xop, "field format missing format character: %s", fmt); xf.xf_fc = *cp; if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) { if (*cp == 's' || *cp == 'S') { /* Handle "%*.*.*s" */ int s; for (s = 0; s < XF_WIDTH_NUM; s++) { if (xf.xf_star[s]) { xf.xf_width[s] = va_arg(xop->xo_vap, int); /* Normalize a negative width value */ if (xf.xf_width[s] < 0) { if (s == 0) { xf.xf_width[0] = -xf.xf_width[0]; xf.xf_seen_minus = 1; } else xf.xf_width[s] = -1; /* Ignore negative values */ } } } } } /* If no max is given, it defaults to size */ if (xf.xf_width[XF_WIDTH_MAX] < 0 && xf.xf_width[XF_WIDTH_SIZE] >= 0) xf.xf_width[XF_WIDTH_MAX] = xf.xf_width[XF_WIDTH_SIZE]; if (xf.xf_fc == 'D' || xf.xf_fc == 'O' || xf.xf_fc == 'U') xf.xf_lflag = 1; if (!xf.xf_skip) { xo_buffer_t *fbp = &xop->xo_fmt; ssize_t len = cp - sp + 1; if (!xo_buf_has_room(fbp, len + 1)) return -1; char *newfmt = fbp->xb_curp; memcpy(newfmt, sp, len); newfmt[0] = '%'; /* If we skipped over a "%@...@s" format */ newfmt[len] = '\0'; /* * Bad news: our strings are UTF-8, but the stock printf * functions won't handle field widths for wide characters * correctly. So we have to handle this ourselves. */ if (xop->xo_formatter == NULL && (xf.xf_fc == 's' || xf.xf_fc == 'S' || xf.xf_fc == 'm')) { xf.xf_enc = (xf.xf_fc == 'm') ? XF_ENC_UTF8 : (xf.xf_lflag || (xf.xf_fc == 'S')) ? XF_ENC_WIDE : xf.xf_hflag ? XF_ENC_LOCALE : XF_ENC_UTF8; rc = xo_format_string(xop, xbp, flags, &xf); if ((flags & XFF_TRIM_WS) && xo_style_is_encoding(xop)) rc = xo_trim_ws(xbp, rc); } else { ssize_t columns = rc = xo_vsnprintf(xop, xbp, newfmt, xop->xo_vap); /* * For XML and HTML, we need "&<>" processing; for JSON, * it's quotes. Text gets nothing. */ switch (style) { case XO_STYLE_XML: if (flags & XFF_TRIM_WS) columns = rc = xo_trim_ws(xbp, rc); /* FALLTHRU */ case XO_STYLE_HTML: rc = xo_escape_xml(xbp, rc, (flags & XFF_ATTR)); break; case XO_STYLE_JSON: if (flags & XFF_TRIM_WS) columns = rc = xo_trim_ws(xbp, rc); rc = xo_escape_json(xbp, rc, 0); break; case XO_STYLE_SDPARAMS: if (flags & XFF_TRIM_WS) columns = rc = xo_trim_ws(xbp, rc); rc = xo_escape_sdparams(xbp, rc, 0); break; case XO_STYLE_ENCODER: if (flags & XFF_TRIM_WS) columns = rc = xo_trim_ws(xbp, rc); break; } /* * We can assume all the non-%s data we've * added is ASCII, so the columns and bytes are the * same. xo_format_string handles all the fancy * string conversions and updates xo_anchor_columns * accordingly. */ if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += columns; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += columns; } xbp->xb_curp += rc; } /* * Now for the tricky part: we need to move the argument pointer * along by the amount needed. */ if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) { if (xf.xf_fc == 's' ||xf.xf_fc == 'S') { /* * The 'S' and 's' formats are normally handled in * xo_format_string, but if we skipped it, then we * need to pop it. */ if (xf.xf_skip) va_arg(xop->xo_vap, char *); } else if (xf.xf_fc == 'm') { /* Nothing on the stack for "%m" */ } else { int s; for (s = 0; s < XF_WIDTH_NUM; s++) { if (xf.xf_star[s]) va_arg(xop->xo_vap, int); } if (strchr("diouxXDOU", xf.xf_fc) != NULL) { if (xf.xf_hflag > 1) { va_arg(xop->xo_vap, int); } else if (xf.xf_hflag > 0) { va_arg(xop->xo_vap, int); } else if (xf.xf_lflag > 1) { va_arg(xop->xo_vap, unsigned long long); } else if (xf.xf_lflag > 0) { va_arg(xop->xo_vap, unsigned long); } else if (xf.xf_jflag > 0) { va_arg(xop->xo_vap, intmax_t); } else if (xf.xf_tflag > 0) { va_arg(xop->xo_vap, ptrdiff_t); } else if (xf.xf_zflag > 0) { va_arg(xop->xo_vap, size_t); } else if (xf.xf_qflag > 0) { va_arg(xop->xo_vap, quad_t); } else { va_arg(xop->xo_vap, int); } } else if (strchr("eEfFgGaA", xf.xf_fc) != NULL) if (xf.xf_lflag) va_arg(xop->xo_vap, long double); else va_arg(xop->xo_vap, double); else if (xf.xf_fc == 'C' || (xf.xf_fc == 'c' && xf.xf_lflag)) va_arg(xop->xo_vap, wint_t); else if (xf.xf_fc == 'c') va_arg(xop->xo_vap, int); else if (xf.xf_fc == 'p') va_arg(xop->xo_vap, void *); } } } if (xp) { if (make_output) { cols = xo_format_string_direct(xop, xbp, flags | XFF_UNESCAPE, NULL, xp, cp - xp, -1, need_enc, XF_ENC_UTF8); if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += cols; } xp = NULL; } if (flags & XFF_GT_FLAGS) { /* * Handle gettext()ing the field by looking up the value * and then copying it in, while converting to locale, if * needed. */ ssize_t new_cols = xo_format_gettext(xop, flags, start_offset, old_cols, real_need_enc); if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += new_cols - old_cols; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += new_cols - old_cols; } return 0; } /* * Remove any numeric precision/width format from the format string by * inserting the "%" after the [0-9]+, returning the substring. */ static char * xo_fix_encoding (xo_handle_t *xop UNUSED, char *encoding) { char *cp = encoding; if (cp[0] != '%' || !isdigit((int) cp[1])) return encoding; for (cp += 2; *cp; cp++) { if (!isdigit((int) *cp)) break; } *--cp = '%'; /* Back off and insert the '%' */ return cp; } static void xo_color_append_html (xo_handle_t *xop) { /* * If the color buffer has content, we add it now. It's already * prebuilt and ready, since we want to add it to every
. */ if (!xo_buf_is_empty(&xop->xo_color_buf)) { xo_buffer_t *xbp = &xop->xo_color_buf; xo_data_append(xop, xbp->xb_bufp, xbp->xb_curp - xbp->xb_bufp); } } /* * A wrapper for humanize_number that autoscales, since the * HN_AUTOSCALE flag scales as needed based on the size of * the output buffer, not the size of the value. I also * wish HN_DECIMAL was more imperative, without the <10 * test. But the boat only goes where we want when we hold * the rudder, so xo_humanize fixes part of the problem. */ static ssize_t xo_humanize (char *buf, ssize_t len, uint64_t value, int flags) { int scale = 0; if (value) { uint64_t left = value; if (flags & HN_DIVISOR_1000) { for ( ; left; scale++) left /= 1000; } else { for ( ; left; scale++) left /= 1024; } scale -= 1; } return xo_humanize_number(buf, len, value, "", scale, flags); } /* * This is an area where we can save information from the handle for * later restoration. We need to know what data was rendered to know * what needs cleaned up. */ typedef struct xo_humanize_save_s { ssize_t xhs_offset; /* Saved xo_offset */ ssize_t xhs_columns; /* Saved xo_columns */ ssize_t xhs_anchor_columns; /* Saved xo_anchor_columns */ } xo_humanize_save_t; /* * Format a "humanized" value for a numeric, meaning something nice * like "44M" instead of "44470272". We autoscale, choosing the * most appropriate value for K/M/G/T/P/E based on the value given. */ static void xo_format_humanize (xo_handle_t *xop, xo_buffer_t *xbp, xo_humanize_save_t *savep, xo_xff_flags_t flags) { if (XOF_ISSET(xop, XOF_NO_HUMANIZE)) return; ssize_t end_offset = xbp->xb_curp - xbp->xb_bufp; if (end_offset == savep->xhs_offset) /* Huh? Nothing to render */ return; /* * We have a string that's allegedly a number. We want to * humanize it, which means turning it back into a number * and calling xo_humanize_number on it. */ uint64_t value; char *ep; xo_buf_append(xbp, "", 1); /* NUL-terminate it */ value = strtoull(xbp->xb_bufp + savep->xhs_offset, &ep, 0); if (!(value == ULLONG_MAX && errno == ERANGE) && (ep != xbp->xb_bufp + savep->xhs_offset)) { /* * There are few values where humanize_number needs * more bytes than the original value. I've used * 10 as a rectal number to cover those scenarios. */ if (xo_buf_has_room(xbp, 10)) { xbp->xb_curp = xbp->xb_bufp + savep->xhs_offset; ssize_t rc; ssize_t left = (xbp->xb_bufp + xbp->xb_size) - xbp->xb_curp; int hn_flags = HN_NOSPACE; /* On by default */ if (flags & XFF_HN_SPACE) hn_flags &= ~HN_NOSPACE; if (flags & XFF_HN_DECIMAL) hn_flags |= HN_DECIMAL; if (flags & XFF_HN_1000) hn_flags |= HN_DIVISOR_1000; rc = xo_humanize(xbp->xb_curp, left, value, hn_flags); if (rc > 0) { xbp->xb_curp += rc; xop->xo_columns = savep->xhs_columns + rc; xop->xo_anchor_columns = savep->xhs_anchor_columns + rc; } } } } /* * Convenience function that either append a fixed value (if one is * given) or formats a field using a format string. If it's * encode_only, then we can't skip formatting the field, since it may * be pulling arguments off the stack. */ static inline void xo_simple_field (xo_handle_t *xop, unsigned encode_only, const char *value, ssize_t vlen, const char *fmt, ssize_t flen, xo_xff_flags_t flags) { if (encode_only) flags |= XFF_NO_OUTPUT; if (vlen == 0) xo_do_format_field(xop, NULL, fmt, flen, flags); else if (!encode_only) xo_data_append_content(xop, value, vlen, flags); } /* * Html mode: append a
to the output buffer contain a field * along with all the supporting information indicated by the flags. */ static void xo_buf_append_div (xo_handle_t *xop, const char *class, xo_xff_flags_t flags, const char *name, ssize_t nlen, const char *value, ssize_t vlen, const char *fmt, ssize_t flen, const char *encoding, ssize_t elen) { static char div_start[] = "
"; static char div_close[] = "
"; /* The encoding format defaults to the normal format */ if (encoding == NULL && fmt != NULL) { char *enc = alloca(flen + 1); memcpy(enc, fmt, flen); enc[flen] = '\0'; encoding = xo_fix_encoding(xop, enc); elen = strlen(encoding); } /* * To build our XPath predicate, we need to save the va_list before * we format our data, and then restore it before we format the * xpath expression. * Display-only keys implies that we've got an encode-only key * elsewhere, so we don't use them from making predicates. */ int need_predidate = (name && (flags & XFF_KEY) && !(flags & XFF_DISPLAY_ONLY) && XOF_ISSET(xop, XOF_XPATH)) ? 1 : 0; if (need_predidate) { va_list va_local; va_copy(va_local, xop->xo_vap); if (xop->xo_checkpointer) xop->xo_checkpointer(xop, xop->xo_vap, 0); /* * Build an XPath predicate expression to match this key. * We use the format buffer. */ xo_buffer_t *pbp = &xop->xo_predicate; pbp->xb_curp = pbp->xb_bufp; /* Restart buffer */ xo_buf_append(pbp, "[", 1); xo_buf_escape(xop, pbp, name, nlen, 0); if (XOF_ISSET(xop, XOF_PRETTY)) xo_buf_append(pbp, " = '", 4); else xo_buf_append(pbp, "='", 2); xo_xff_flags_t pflags = flags | XFF_XML | XFF_ATTR; pflags &= ~(XFF_NO_OUTPUT | XFF_ENCODE_ONLY); xo_do_format_field(xop, pbp, encoding, elen, pflags); xo_buf_append(pbp, "']", 2); /* Now we record this predicate expression in the stack */ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; ssize_t olen = xsp->xs_keys ? strlen(xsp->xs_keys) : 0; ssize_t dlen = pbp->xb_curp - pbp->xb_bufp; char *cp = xo_realloc(xsp->xs_keys, olen + dlen + 1); if (cp) { memcpy(cp + olen, pbp->xb_bufp, dlen); cp[olen + dlen] = '\0'; xsp->xs_keys = cp; } /* Now we reset the xo_vap as if we were never here */ va_end(xop->xo_vap); va_copy(xop->xo_vap, va_local); va_end(va_local); if (xop->xo_checkpointer) xop->xo_checkpointer(xop, xop->xo_vap, 1); } if (flags & XFF_ENCODE_ONLY) { /* * Even if this is encode-only, we need to go through the * work of formatting it to make sure the args are cleared * from xo_vap. This is not true when vlen is zero, since * that means our "value" isn't on the stack. */ xo_simple_field(xop, TRUE, NULL, 0, encoding, elen, flags); return; } xo_line_ensure_open(xop, 0); if (XOF_ISSET(xop, XOF_PRETTY)) xo_buf_indent(xop, xop->xo_indent_by); xo_data_append(xop, div_start, sizeof(div_start) - 1); xo_data_append(xop, class, strlen(class)); /* * If the color buffer has content, we add it now. It's already * prebuilt and ready, since we want to add it to every
. */ if (!xo_buf_is_empty(&xop->xo_color_buf)) { xo_buffer_t *xbp = &xop->xo_color_buf; xo_data_append(xop, xbp->xb_bufp, xbp->xb_curp - xbp->xb_bufp); } if (name) { xo_data_append(xop, div_tag, sizeof(div_tag) - 1); xo_data_escape(xop, name, nlen); /* * Save the offset at which we'd place units. See xo_format_units. */ if (XOF_ISSET(xop, XOF_UNITS)) { XOIF_SET(xop, XOIF_UNITS_PENDING); /* * Note: We need the '+1' here because we know we've not * added the closing quote. We add one, knowing the quote * will be added shortly. */ xop->xo_units_offset = xop->xo_data.xb_curp -xop->xo_data.xb_bufp + 1; } if (XOF_ISSET(xop, XOF_XPATH)) { int i; xo_stack_t *xsp; xo_data_append(xop, div_xpath, sizeof(div_xpath) - 1); if (xop->xo_leading_xpath) xo_data_append(xop, xop->xo_leading_xpath, strlen(xop->xo_leading_xpath)); for (i = 0; i <= xop->xo_depth; i++) { xsp = &xop->xo_stack[i]; if (xsp->xs_name == NULL) continue; /* * XSS_OPEN_LIST and XSS_OPEN_LEAF_LIST stack frames * are directly under XSS_OPEN_INSTANCE frames so we * don't need to put these in our XPath expressions. */ if (xsp->xs_state == XSS_OPEN_LIST || xsp->xs_state == XSS_OPEN_LEAF_LIST) continue; xo_data_append(xop, "/", 1); xo_data_escape(xop, xsp->xs_name, strlen(xsp->xs_name)); if (xsp->xs_keys) { /* Don't show keys for the key field */ if (i != xop->xo_depth || !(flags & XFF_KEY)) xo_data_append(xop, xsp->xs_keys, strlen(xsp->xs_keys)); } } xo_data_append(xop, "/", 1); xo_data_escape(xop, name, nlen); } if (XOF_ISSET(xop, XOF_INFO) && xop->xo_info) { static char in_type[] = "\" data-type=\""; static char in_help[] = "\" data-help=\""; xo_info_t *xip = xo_info_find(xop, name, nlen); if (xip) { if (xip->xi_type) { xo_data_append(xop, in_type, sizeof(in_type) - 1); xo_data_escape(xop, xip->xi_type, strlen(xip->xi_type)); } if (xip->xi_help) { xo_data_append(xop, in_help, sizeof(in_help) - 1); xo_data_escape(xop, xip->xi_help, strlen(xip->xi_help)); } } } if ((flags & XFF_KEY) && XOF_ISSET(xop, XOF_KEYS)) xo_data_append(xop, div_key, sizeof(div_key) - 1); } xo_buffer_t *xbp = &xop->xo_data; ssize_t base_offset = xbp->xb_curp - xbp->xb_bufp; xo_data_append(xop, div_end, sizeof(div_end) - 1); xo_humanize_save_t save; /* Save values for humanizing logic */ save.xhs_offset = xbp->xb_curp - xbp->xb_bufp; save.xhs_columns = xop->xo_columns; save.xhs_anchor_columns = xop->xo_anchor_columns; xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (flags & XFF_HUMANIZE) { /* * Unlike text style, we want to retain the original value and * stuff it into the "data-number" attribute. */ static const char div_number[] = "\" data-number=\""; ssize_t div_len = sizeof(div_number) - 1; ssize_t end_offset = xbp->xb_curp - xbp->xb_bufp; ssize_t olen = end_offset - save.xhs_offset; char *cp = alloca(olen + 1); memcpy(cp, xbp->xb_bufp + save.xhs_offset, olen); cp[olen] = '\0'; xo_format_humanize(xop, xbp, &save, flags); if (xo_buf_has_room(xbp, div_len + olen)) { ssize_t new_offset = xbp->xb_curp - xbp->xb_bufp; /* Move the humanized string off to the left */ memmove(xbp->xb_bufp + base_offset + div_len + olen, xbp->xb_bufp + base_offset, new_offset - base_offset); /* Copy the data_number attribute name */ memcpy(xbp->xb_bufp + base_offset, div_number, div_len); /* Copy the original long value */ memcpy(xbp->xb_bufp + base_offset + div_len, cp, olen); xbp->xb_curp += div_len + olen; } } xo_data_append(xop, div_close, sizeof(div_close) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); } static void xo_format_text (xo_handle_t *xop, const char *str, ssize_t len) { switch (xo_style(xop)) { case XO_STYLE_TEXT: xo_buf_append_locale(xop, &xop->xo_data, str, len); break; case XO_STYLE_HTML: xo_buf_append_div(xop, "text", 0, NULL, 0, str, len, NULL, 0, NULL, 0); break; } } static void xo_format_title (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; xo_xff_flags_t flags = xfip->xfi_flags; static char div_open[] = "
"; static char div_close[] = "
"; if (flen == 0) { fmt = "%s"; flen = 2; } switch (xo_style(xop)) { case XO_STYLE_XML: case XO_STYLE_JSON: case XO_STYLE_SDPARAMS: case XO_STYLE_ENCODER: /* * Even though we don't care about text, we need to do * enough parsing work to skip over the right bits of xo_vap. */ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); return; } xo_buffer_t *xbp = &xop->xo_data; ssize_t start = xbp->xb_curp - xbp->xb_bufp; ssize_t left = xbp->xb_size - start; ssize_t rc; if (xo_style(xop) == XO_STYLE_HTML) { xo_line_ensure_open(xop, 0); if (XOF_ISSET(xop, XOF_PRETTY)) xo_buf_indent(xop, xop->xo_indent_by); xo_buf_append(&xop->xo_data, div_open, sizeof(div_open) - 1); xo_color_append_html(xop); xo_buf_append(&xop->xo_data, div_middle, sizeof(div_middle) - 1); } start = xbp->xb_curp - xbp->xb_bufp; /* Reset start */ if (vlen) { char *newfmt = alloca(flen + 1); memcpy(newfmt, fmt, flen); newfmt[flen] = '\0'; /* If len is non-zero, the format string apply to the name */ char *newstr = alloca(vlen + 1); memcpy(newstr, value, vlen); newstr[vlen] = '\0'; if (newstr[vlen - 1] == 's') { char *bp; rc = snprintf(NULL, 0, newfmt, newstr); if (rc > 0) { /* * We have to do this the hard way, since we might need * the columns. */ bp = alloca(rc + 1); rc = snprintf(bp, rc + 1, newfmt, newstr); xo_data_append_content(xop, bp, rc, flags); } goto move_along; } else { rc = snprintf(xbp->xb_curp, left, newfmt, newstr); if (rc >= left) { if (!xo_buf_has_room(xbp, rc)) return; left = xbp->xb_size - (xbp->xb_curp - xbp->xb_bufp); rc = snprintf(xbp->xb_curp, left, newfmt, newstr); } if (rc > 0) { if (XOF_ISSET(xop, XOF_COLUMNS)) xop->xo_columns += rc; if (XOIF_ISSET(xop, XOIF_ANCHOR)) xop->xo_anchor_columns += rc; } } } else { xo_do_format_field(xop, NULL, fmt, flen, flags); /* xo_do_format_field moved curp, so we need to reset it */ rc = xbp->xb_curp - (xbp->xb_bufp + start); xbp->xb_curp = xbp->xb_bufp + start; } /* If we're styling HTML, then we need to escape it */ if (xo_style(xop) == XO_STYLE_HTML) { rc = xo_escape_xml(xbp, rc, 0); } if (rc > 0) xbp->xb_curp += rc; move_along: if (xo_style(xop) == XO_STYLE_HTML) { xo_data_append(xop, div_close, sizeof(div_close) - 1); if (XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); } } static void xo_format_prep (xo_handle_t *xop, xo_xff_flags_t flags) { if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) { xo_data_append(xop, ",", 1); if (!(flags & XFF_LEAF_LIST) && XOF_ISSET(xop, XOF_PRETTY)) xo_data_append(xop, "\n", 1); } else xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; } #if 0 /* Useful debugging function */ void xo_arg (xo_handle_t *xop); void xo_arg (xo_handle_t *xop) { xop = xo_default(xop); fprintf(stderr, "0x%x", va_arg(xop->xo_vap, unsigned)); } #endif /* 0 */ static void xo_format_value (xo_handle_t *xop, const char *name, ssize_t nlen, const char *value, ssize_t vlen, const char *fmt, ssize_t flen, const char *encoding, ssize_t elen, xo_xff_flags_t flags) { int pretty = XOF_ISSET(xop, XOF_PRETTY); int quote; /* * Before we emit a value, we need to know that the frame is ready. */ xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; if (flags & XFF_LEAF_LIST) { /* * Check if we've already started to emit normal leafs * or if we're not in a leaf list. */ if ((xsp->xs_flags & (XSF_EMIT | XSF_EMIT_KEY)) || !(xsp->xs_flags & XSF_EMIT_LEAF_LIST)) { char nbuf[nlen + 1]; memcpy(nbuf, name, nlen); nbuf[nlen] = '\0'; ssize_t rc = xo_transition(xop, 0, nbuf, XSS_EMIT_LEAF_LIST); if (rc < 0) flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; else xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_LEAF_LIST; } xsp = &xop->xo_stack[xop->xo_depth]; if (xsp->xs_name) { name = xsp->xs_name; nlen = strlen(name); } } else if (flags & XFF_KEY) { /* Emitting a 'k' (key) field */ if ((xsp->xs_flags & XSF_EMIT) && !(flags & XFF_DISPLAY_ONLY)) { xo_failure(xop, "key field emitted after normal value field: '%.*s'", nlen, name); } else if (!(xsp->xs_flags & XSF_EMIT_KEY)) { char nbuf[nlen + 1]; memcpy(nbuf, name, nlen); nbuf[nlen] = '\0'; ssize_t rc = xo_transition(xop, 0, nbuf, XSS_EMIT); if (rc < 0) flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; else xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT_KEY; xsp = &xop->xo_stack[xop->xo_depth]; xsp->xs_flags |= XSF_EMIT_KEY; } } else { /* Emitting a normal value field */ if ((xsp->xs_flags & XSF_EMIT_LEAF_LIST) || !(xsp->xs_flags & XSF_EMIT)) { char nbuf[nlen + 1]; memcpy(nbuf, name, nlen); nbuf[nlen] = '\0'; ssize_t rc = xo_transition(xop, 0, nbuf, XSS_EMIT); if (rc < 0) flags |= XFF_DISPLAY_ONLY | XFF_ENCODE_ONLY; else xop->xo_stack[xop->xo_depth].xs_flags |= XSF_EMIT; xsp = &xop->xo_stack[xop->xo_depth]; xsp->xs_flags |= XSF_EMIT; } } xo_buffer_t *xbp = &xop->xo_data; xo_humanize_save_t save; /* Save values for humanizing logic */ switch (xo_style(xop)) { case XO_STYLE_TEXT: if (flags & XFF_ENCODE_ONLY) flags |= XFF_NO_OUTPUT; save.xhs_offset = xbp->xb_curp - xbp->xb_bufp; save.xhs_columns = xop->xo_columns; save.xhs_anchor_columns = xop->xo_anchor_columns; xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (flags & XFF_HUMANIZE) xo_format_humanize(xop, xbp, &save, flags); break; case XO_STYLE_HTML: if (flags & XFF_ENCODE_ONLY) flags |= XFF_NO_OUTPUT; xo_buf_append_div(xop, "data", flags, name, nlen, value, vlen, fmt, flen, encoding, elen); break; case XO_STYLE_XML: /* * Even though we're not making output, we still need to * let the formatting code handle the va_arg popping. */ if (flags & XFF_DISPLAY_ONLY) { xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); memcpy(enc, fmt, flen); enc[flen] = '\0'; fmt = xo_fix_encoding(xop, enc); flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } if (pretty) xo_buf_indent(xop, -1); xo_data_append(xop, "<", 1); xo_data_escape(xop, name, nlen); if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) { xo_data_append(xop, xop->xo_attrs.xb_bufp, xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp); xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp; } /* * We indicate 'key' fields using the 'key' attribute. While * this is really committing the crime of mixing meta-data with * data, it's often useful. Especially when format meta-data is * difficult to come by. */ if ((flags & XFF_KEY) && XOF_ISSET(xop, XOF_KEYS)) { static char attr[] = " key=\"key\""; xo_data_append(xop, attr, sizeof(attr) - 1); } /* * Save the offset at which we'd place units. See xo_format_units. */ if (XOF_ISSET(xop, XOF_UNITS)) { XOIF_SET(xop, XOIF_UNITS_PENDING); xop->xo_units_offset = xop->xo_data.xb_curp -xop->xo_data.xb_bufp; } xo_data_append(xop, ">", 1); xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); xo_data_append(xop, "", 1); if (pretty) xo_data_append(xop, "\n", 1); break; case XO_STYLE_JSON: if (flags & XFF_DISPLAY_ONLY) { xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); memcpy(enc, fmt, flen); enc[flen] = '\0'; fmt = xo_fix_encoding(xop, enc); flen = strlen(fmt); } int first = (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) ? 0 : 1; xo_format_prep(xop, flags); if (flags & XFF_QUOTE) quote = 1; else if (flags & XFF_NOQUOTE) quote = 0; else if (vlen != 0) quote = 1; else if (flen == 0) { quote = 0; fmt = "true"; /* JSON encodes empty tags as a boolean true */ flen = 4; } else if (strchr("diouDOUeEfFgG", fmt[flen - 1]) == NULL) quote = 1; else quote = 0; if (nlen == 0) { static char missing[] = "missing-field-name"; xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } if (flags & XFF_LEAF_LIST) { if (!first && pretty) xo_data_append(xop, "\n", 1); if (pretty) xo_buf_indent(xop, -1); } else { if (pretty) xo_buf_indent(xop, -1); xo_data_append(xop, "\"", 1); xbp = &xop->xo_data; ssize_t off = xbp->xb_curp - xbp->xb_bufp; xo_data_escape(xop, name, nlen); if (XOF_ISSET(xop, XOF_UNDERSCORES)) { ssize_t coff = xbp->xb_curp - xbp->xb_bufp; for ( ; off < coff; off++) if (xbp->xb_bufp[off] == '-') xbp->xb_bufp[off] = '_'; } xo_data_append(xop, "\":", 2); if (pretty) xo_data_append(xop, " ", 1); } if (quote) xo_data_append(xop, "\"", 1); xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); if (quote) xo_data_append(xop, "\"", 1); break; case XO_STYLE_SDPARAMS: if (flags & XFF_DISPLAY_ONLY) { xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (encoding) { fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); memcpy(enc, fmt, flen); enc[flen] = '\0'; fmt = xo_fix_encoding(xop, enc); flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } xo_data_escape(xop, name, nlen); xo_data_append(xop, "=\"", 2); xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); xo_data_append(xop, "\" ", 2); break; case XO_STYLE_ENCODER: if (flags & XFF_DISPLAY_ONLY) { xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } if (flags & XFF_QUOTE) quote = 1; else if (flags & XFF_NOQUOTE) quote = 0; else if (flen == 0) { quote = 0; fmt = "true"; /* JSON encodes empty tags as a boolean true */ flen = 4; } else if (strchr("diouxXDOUeEfFgGaAcCp", fmt[flen - 1]) == NULL) quote = 1; else quote = 0; if (encoding) { fmt = encoding; flen = elen; } else { char *enc = alloca(flen + 1); memcpy(enc, fmt, flen); enc[flen] = '\0'; fmt = xo_fix_encoding(xop, enc); flen = strlen(fmt); } if (nlen == 0) { static char missing[] = "missing-field-name"; xo_failure(xop, "missing field name: %s", fmt); name = missing; nlen = sizeof(missing) - 1; } ssize_t name_offset = xo_buf_offset(&xop->xo_data); xo_data_append(xop, name, nlen); xo_data_append(xop, "", 1); ssize_t value_offset = xo_buf_offset(&xop->xo_data); xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); xo_data_append(xop, "", 1); xo_encoder_handle(xop, quote ? XO_OP_STRING : XO_OP_CONTENT, xo_buf_data(&xop->xo_data, name_offset), xo_buf_data(&xop->xo_data, value_offset), flags); xo_buf_reset(&xop->xo_data); break; } } static void xo_set_gettext_domain (xo_handle_t *xop, xo_field_info_t *xfip, const char *str, ssize_t len) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; /* Start by discarding previous domain */ if (xop->xo_gt_domain) { xo_free(xop->xo_gt_domain); xop->xo_gt_domain = NULL; } /* An empty {G:} means no domainname */ if (len == 0 && flen == 0) return; ssize_t start_offset = -1; if (len == 0 && flen != 0) { /* Need to do format the data to get the domainname from args */ start_offset = xop->xo_data.xb_curp - xop->xo_data.xb_bufp; xo_do_format_field(xop, NULL, fmt, flen, 0); ssize_t end_offset = xop->xo_data.xb_curp - xop->xo_data.xb_bufp; len = end_offset - start_offset; str = xop->xo_data.xb_bufp + start_offset; } xop->xo_gt_domain = xo_strndup(str, len); /* Reset the current buffer point to avoid emitting the name as output */ if (start_offset >= 0) xop->xo_data.xb_curp = xop->xo_data.xb_bufp + start_offset; } static void xo_format_content (xo_handle_t *xop, const char *class_name, const char *tag_name, const char *value, ssize_t vlen, const char *fmt, ssize_t flen, xo_xff_flags_t flags) { switch (xo_style(xop)) { case XO_STYLE_TEXT: xo_simple_field(xop, FALSE, value, vlen, fmt, flen, flags); break; case XO_STYLE_HTML: xo_buf_append_div(xop, class_name, flags, NULL, 0, value, vlen, fmt, flen, NULL, 0); break; case XO_STYLE_XML: case XO_STYLE_JSON: case XO_STYLE_SDPARAMS: if (tag_name) { xo_open_container_h(xop, tag_name); xo_format_value(xop, "message", 7, value, vlen, fmt, flen, NULL, 0, flags); xo_close_container_h(xop, tag_name); } else { /* * Even though we don't care about labels, we need to do * enough parsing work to skip over the right bits of xo_vap. */ xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); } break; case XO_STYLE_ENCODER: xo_simple_field(xop, TRUE, value, vlen, fmt, flen, flags); break; } } static const char *xo_color_names[] = { "default", /* XO_COL_DEFAULT */ "black", /* XO_COL_BLACK */ "red", /* XO_CLOR_RED */ "green", /* XO_COL_GREEN */ "yellow", /* XO_COL_YELLOW */ "blue", /* XO_COL_BLUE */ "magenta", /* XO_COL_MAGENTA */ "cyan", /* XO_COL_CYAN */ "white", /* XO_COL_WHITE */ NULL }; static int xo_color_find (const char *str) { int i; for (i = 0; xo_color_names[i]; i++) { if (strcmp(xo_color_names[i], str) == 0) return i; } return -1; } static const char *xo_effect_names[] = { "reset", /* XO_EFF_RESET */ "normal", /* XO_EFF_NORMAL */ "bold", /* XO_EFF_BOLD */ "underline", /* XO_EFF_UNDERLINE */ "inverse", /* XO_EFF_INVERSE */ NULL }; static const char *xo_effect_on_codes[] = { "0", /* XO_EFF_RESET */ "0", /* XO_EFF_NORMAL */ "1", /* XO_EFF_BOLD */ "4", /* XO_EFF_UNDERLINE */ "7", /* XO_EFF_INVERSE */ NULL }; #if 0 /* * See comment below re: joy of terminal standards. These can * be use by just adding: * + if (newp->xoc_effects & bit) * code = xo_effect_on_codes[i]; * + else * + code = xo_effect_off_codes[i]; * in xo_color_handle_text. */ static const char *xo_effect_off_codes[] = { "0", /* XO_EFF_RESET */ "0", /* XO_EFF_NORMAL */ "21", /* XO_EFF_BOLD */ "24", /* XO_EFF_UNDERLINE */ "27", /* XO_EFF_INVERSE */ NULL }; #endif /* 0 */ static int xo_effect_find (const char *str) { int i; for (i = 0; xo_effect_names[i]; i++) { if (strcmp(xo_effect_names[i], str) == 0) return i; } return -1; } static void xo_colors_parse (xo_handle_t *xop, xo_colors_t *xocp, char *str) { #ifdef LIBXO_TEXT_ONLY return; #endif /* LIBXO_TEXT_ONLY */ char *cp, *ep, *np, *xp; ssize_t len = strlen(str); int rc; /* * Possible tokens: colors, bg-colors, effects, no-effects, "reset". */ for (cp = str, ep = cp + len - 1; cp && cp < ep; cp = np) { /* Trim leading whitespace */ while (isspace((int) *cp)) cp += 1; np = strchr(cp, ','); if (np) *np++ = '\0'; /* Trim trailing whitespace */ xp = cp + strlen(cp) - 1; while (isspace(*xp) && xp > cp) *xp-- = '\0'; if (cp[0] == 'f' && cp[1] == 'g' && cp[2] == '-') { rc = xo_color_find(cp + 3); if (rc < 0) goto unknown; xocp->xoc_col_fg = rc; } else if (cp[0] == 'b' && cp[1] == 'g' && cp[2] == '-') { rc = xo_color_find(cp + 3); if (rc < 0) goto unknown; xocp->xoc_col_bg = rc; } else if (cp[0] == 'n' && cp[1] == 'o' && cp[2] == '-') { rc = xo_effect_find(cp + 3); if (rc < 0) goto unknown; xocp->xoc_effects &= ~(1 << rc); } else { rc = xo_effect_find(cp); if (rc < 0) goto unknown; xocp->xoc_effects |= 1 << rc; switch (1 << rc) { case XO_EFF_RESET: xocp->xoc_col_fg = xocp->xoc_col_bg = 0; /* Note: not "|=" since we want to wipe out the old value */ xocp->xoc_effects = XO_EFF_RESET; break; case XO_EFF_NORMAL: xocp->xoc_effects &= ~(XO_EFF_BOLD | XO_EFF_UNDERLINE | XO_EFF_INVERSE | XO_EFF_NORMAL); break; } } continue; unknown: if (XOF_ISSET(xop, XOF_WARN)) xo_failure(xop, "unknown color/effect string detected: '%s'", cp); } } static inline int xo_colors_enabled (xo_handle_t *xop UNUSED) { #ifdef LIBXO_TEXT_ONLY return 0; #else /* LIBXO_TEXT_ONLY */ return XOF_ISSET(xop, XOF_COLOR); #endif /* LIBXO_TEXT_ONLY */ } /* * If the color map is in use (--libxo colors=xxxx), then update * the incoming foreground and background colors from the map. */ static void xo_colors_update (xo_handle_t *xop, xo_colors_t *newp) { #ifdef LIBXO_TEXT_ONLY return; #endif /* LIBXO_TEXT_ONLY */ xo_color_t fg = newp->xoc_col_fg; if (XOF_ISSET(xop, XOF_COLOR_MAP) && fg < XO_NUM_COLORS) fg = xop->xo_color_map_fg[fg]; /* Fetch from color map */ newp->xoc_col_fg = fg; xo_color_t bg = newp->xoc_col_bg; if (XOF_ISSET(xop, XOF_COLOR_MAP) && bg < XO_NUM_COLORS) bg = xop->xo_color_map_bg[bg]; /* Fetch from color map */ newp->xoc_col_bg = bg; } static void xo_colors_handle_text (xo_handle_t *xop, xo_colors_t *newp) { char buf[BUFSIZ]; char *cp = buf, *ep = buf + sizeof(buf); unsigned i, bit; xo_colors_t *oldp = &xop->xo_colors; const char *code = NULL; /* * Start the buffer with an escape. We don't want to add the '[' * now, since we let xo_effect_text_add unconditionally add the ';'. * We'll replace the first ';' with a '[' when we're done. */ *cp++ = 0x1b; /* Escape */ /* * Terminals were designed back in the age before "certainty" was * invented, when standards were more what you'd call "guidelines" * than actual rules. Anyway we can't depend on them to operate * correctly. So when display attributes are changed, we punt, * reseting them all and turning back on the ones we want to keep. * Longer, but should be completely reliable. Savvy? */ if (oldp->xoc_effects != (newp->xoc_effects & oldp->xoc_effects)) { newp->xoc_effects |= XO_EFF_RESET; oldp->xoc_effects = 0; } for (i = 0, bit = 1; xo_effect_names[i]; i++, bit <<= 1) { if ((newp->xoc_effects & bit) == (oldp->xoc_effects & bit)) continue; code = xo_effect_on_codes[i]; cp += snprintf(cp, ep - cp, ";%s", code); if (cp >= ep) return; /* Should not occur */ if (bit == XO_EFF_RESET) { /* Mark up the old value so we can detect current values as new */ oldp->xoc_effects = 0; oldp->xoc_col_fg = oldp->xoc_col_bg = XO_COL_DEFAULT; } } xo_color_t fg = newp->xoc_col_fg; if (fg != oldp->xoc_col_fg) { cp += snprintf(cp, ep - cp, ";3%u", (fg != XO_COL_DEFAULT) ? fg - 1 : 9); } xo_color_t bg = newp->xoc_col_bg; if (bg != oldp->xoc_col_bg) { cp += snprintf(cp, ep - cp, ";4%u", (bg != XO_COL_DEFAULT) ? bg - 1 : 9); } if (cp - buf != 1 && cp < ep - 3) { buf[1] = '['; /* Overwrite leading ';' */ *cp++ = 'm'; *cp = '\0'; xo_buf_append(&xop->xo_data, buf, cp - buf); } } static void xo_colors_handle_html (xo_handle_t *xop, xo_colors_t *newp) { xo_colors_t *oldp = &xop->xo_colors; /* * HTML colors are mostly trivial: fill in xo_color_buf with * a set of class tags representing the colors and effects. */ /* If nothing changed, then do nothing */ if (oldp->xoc_effects == newp->xoc_effects && oldp->xoc_col_fg == newp->xoc_col_fg && oldp->xoc_col_bg == newp->xoc_col_bg) return; unsigned i, bit; xo_buffer_t *xbp = &xop->xo_color_buf; xo_buf_reset(xbp); /* We rebuild content after each change */ for (i = 0, bit = 1; xo_effect_names[i]; i++, bit <<= 1) { if (!(newp->xoc_effects & bit)) continue; xo_buf_append_str(xbp, " effect-"); xo_buf_append_str(xbp, xo_effect_names[i]); } const char *fg = NULL; const char *bg = NULL; if (newp->xoc_col_fg != XO_COL_DEFAULT) fg = xo_color_names[newp->xoc_col_fg]; if (newp->xoc_col_bg != XO_COL_DEFAULT) bg = xo_color_names[newp->xoc_col_bg]; if (newp->xoc_effects & XO_EFF_INVERSE) { const char *tmp = fg; fg = bg; bg = tmp; if (fg == NULL) fg = "inverse"; if (bg == NULL) bg = "inverse"; } if (fg) { xo_buf_append_str(xbp, " color-fg-"); xo_buf_append_str(xbp, fg); } if (bg) { xo_buf_append_str(xbp, " color-bg-"); xo_buf_append_str(xbp, bg); } } static void xo_format_colors (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; xo_buffer_t xb; /* If the string is static and we've in an encoding style, bail */ if (vlen != 0 && xo_style_is_encoding(xop)) return; xo_buf_init(&xb); if (vlen) xo_buf_append(&xb, value, vlen); else if (flen) xo_do_format_field(xop, &xb, fmt, flen, 0); else xo_buf_append(&xb, "reset", 6); /* Default if empty */ if (xo_colors_enabled(xop)) { switch (xo_style(xop)) { case XO_STYLE_TEXT: case XO_STYLE_HTML: xo_buf_append(&xb, "", 1); xo_colors_t xoc = xop->xo_colors; xo_colors_parse(xop, &xoc, xb.xb_bufp); xo_colors_update(xop, &xoc); if (xo_style(xop) == XO_STYLE_TEXT) { /* * Text mode means emitting the colors as ANSI character * codes. This will allow people who like colors to have * colors. The issue is, of course conflicting with the * user's perfectly reasonable color scheme. Which leads * to the hell of LSCOLORS, where even app need to have * customization hooks for adjusting colors. Instead we * provide a simpler-but-still-annoying answer where one * can map colors to other colors. */ xo_colors_handle_text(xop, &xoc); xoc.xoc_effects &= ~XO_EFF_RESET; /* After handling it */ } else { /* * HTML output is wrapped in divs, so the color information * must appear in every div until cleared. Most pathetic. * Most unavoidable. */ xoc.xoc_effects &= ~XO_EFF_RESET; /* Before handling effects */ xo_colors_handle_html(xop, &xoc); } xop->xo_colors = xoc; break; case XO_STYLE_XML: case XO_STYLE_JSON: case XO_STYLE_SDPARAMS: case XO_STYLE_ENCODER: /* * Nothing to do; we did all that work just to clear the stack of * formatting arguments. */ break; } } xo_buf_cleanup(&xb); } static void xo_format_units (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; xo_xff_flags_t flags = xfip->xfi_flags; static char units_start_xml[] = " units=\""; static char units_start_html[] = " data-units=\""; if (!XOIF_ISSET(xop, XOIF_UNITS_PENDING)) { xo_format_content(xop, "units", NULL, value, vlen, fmt, flen, flags); return; } xo_buffer_t *xbp = &xop->xo_data; ssize_t start = xop->xo_units_offset; ssize_t stop = xbp->xb_curp - xbp->xb_bufp; if (xo_style(xop) == XO_STYLE_XML) xo_buf_append(xbp, units_start_xml, sizeof(units_start_xml) - 1); else if (xo_style(xop) == XO_STYLE_HTML) xo_buf_append(xbp, units_start_html, sizeof(units_start_html) - 1); else return; if (vlen) xo_data_escape(xop, value, vlen); else xo_do_format_field(xop, NULL, fmt, flen, flags); xo_buf_append(xbp, "\"", 1); ssize_t now = xbp->xb_curp - xbp->xb_bufp; ssize_t delta = now - stop; if (delta <= 0) { /* Strange; no output to move */ xbp->xb_curp = xbp->xb_bufp + stop; /* Reset buffer to prior state */ return; } /* * Now we're in it alright. We've need to insert the unit value * we just created into the right spot. We make a local copy, * move it and then insert our copy. We know there's room in the * buffer, since we're just moving this around. */ char *buf = alloca(delta); memcpy(buf, xbp->xb_bufp + stop, delta); memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start); memmove(xbp->xb_bufp + start, buf, delta); } static ssize_t xo_find_width (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { const char *fmt = xfip->xfi_format; ssize_t flen = xfip->xfi_flen; long width = 0; char *bp; char *cp; if (vlen) { bp = alloca(vlen + 1); /* Make local NUL-terminated copy of value */ memcpy(bp, value, vlen); bp[vlen] = '\0'; width = strtol(bp, &cp, 0); - if (width == LONG_MIN || width == LONG_MAX - || bp == cp || *cp != '\0' ) { + if (width == LONG_MIN || width == LONG_MAX || bp == cp || *cp != '\0') { width = 0; xo_failure(xop, "invalid width for anchor: '%s'", bp); } } else if (flen) { - if (flen != 2 || strncmp("%d", fmt, flen) != 0) - xo_failure(xop, "invalid width format: '%*.*s'", flen, flen, fmt); - if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) - width = va_arg(xop->xo_vap, int); + /* + * We really expect the format for width to be "{:/%d}" or + * "{:/%u}", so if that's the case, we just grab our width off + * the argument list. But we need to avoid optimized logic if + * there's a custom formatter. + */ + if (xop->xo_formatter == NULL && flen == 2 + && strncmp("%d", fmt, flen) == 0) { + if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) + width = va_arg(xop->xo_vap, int); + } else if (xop->xo_formatter == NULL && flen == 2 + && strncmp("%u", fmt, flen) == 0) { + if (!XOF_ISSET(xop, XOF_NO_VA_ARG)) + width = va_arg(xop->xo_vap, unsigned); + } else { + /* + * So we have a format and it's not a simple one like + * "{:/%d}". That means we need to format the field, + * extract the value from the formatted output, and then + * discard that output. + */ + int anchor_was_set = FALSE; + xo_buffer_t *xbp = &xop->xo_data; + ssize_t start_offset = xo_buf_offset(xbp); + bp = xo_buf_cur(xbp); /* Save start of the string */ + cp = NULL; + + if (XOIF_ISSET(xop, XOIF_ANCHOR)) { + XOIF_CLEAR(xop, XOIF_ANCHOR); + anchor_was_set = TRUE; + } + + ssize_t rc = xo_do_format_field(xop, xbp, fmt, flen, 0); + if (rc >= 0) { + xo_buf_append(xbp, "", 1); /* Append a NUL */ + + width = strtol(bp, &cp, 0); + if (width == LONG_MIN || width == LONG_MAX + || bp == cp || *cp != '\0') { + width = 0; + xo_failure(xop, "invalid width for anchor: '%s'", bp); + } + } + + /* Reset the cur pointer to where we found it */ + xbp->xb_curp = xbp->xb_bufp + start_offset; + if (anchor_was_set) + XOIF_SET(xop, XOIF_ANCHOR); + } } return width; } static void xo_anchor_clear (xo_handle_t *xop) { XOIF_CLEAR(xop, XOIF_ANCHOR); xop->xo_anchor_offset = 0; xop->xo_anchor_columns = 0; xop->xo_anchor_min_width = 0; } /* * An anchor is a marker used to delay field width implications. * Imagine the format string "{[:10}{min:%d}/{cur:%d}/{max:%d}{:]}". * We are looking for output like " 1/4/5" * * To make this work, we record the anchor and then return to * format it when the end anchor tag is seen. */ static void xo_anchor_start (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { - if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) - return; - if (XOIF_ISSET(xop, XOIF_ANCHOR)) xo_failure(xop, "the anchor already recording is discarded"); XOIF_SET(xop, XOIF_ANCHOR); xo_buffer_t *xbp = &xop->xo_data; xop->xo_anchor_offset = xbp->xb_curp - xbp->xb_bufp; xop->xo_anchor_columns = 0; /* * Now we find the width, if possible. If it's not there, * we'll get it on the end anchor. */ xop->xo_anchor_min_width = xo_find_width(xop, xfip, value, vlen); } static void xo_anchor_stop (xo_handle_t *xop, xo_field_info_t *xfip, const char *value, ssize_t vlen) { - if (xo_style(xop) != XO_STYLE_TEXT && xo_style(xop) != XO_STYLE_HTML) - return; - if (!XOIF_ISSET(xop, XOIF_ANCHOR)) { xo_failure(xop, "no start anchor"); return; } XOIF_CLEAR(xop, XOIF_UNITS_PENDING); ssize_t width = xo_find_width(xop, xfip, value, vlen); if (width == 0) width = xop->xo_anchor_min_width; if (width == 0) /* No width given; nothing to do */ goto done; xo_buffer_t *xbp = &xop->xo_data; ssize_t start = xop->xo_anchor_offset; ssize_t stop = xbp->xb_curp - xbp->xb_bufp; ssize_t abswidth = (width > 0) ? width : -width; ssize_t blen = abswidth - xop->xo_anchor_columns; if (blen <= 0) /* Already over width */ goto done; if (abswidth > XO_MAX_ANCHOR_WIDTH) { xo_failure(xop, "width over %u are not supported", XO_MAX_ANCHOR_WIDTH); goto done; } /* Make a suitable padding field and emit it */ char *buf = alloca(blen); memset(buf, ' ', blen); xo_format_content(xop, "padding", NULL, buf, blen, NULL, 0, 0); if (width < 0) /* Already left justified */ goto done; ssize_t now = xbp->xb_curp - xbp->xb_bufp; ssize_t delta = now - stop; if (delta <= 0) /* Strange; no output to move */ goto done; /* * Now we're in it alright. We've need to insert the padding data * we just created (which might be an HTML
or text) before * the formatted data. We make a local copy, move it and then * insert our copy. We know there's room in the buffer, since * we're just moving this around. */ if (delta > blen) buf = alloca(delta); /* Expand buffer if needed */ memcpy(buf, xbp->xb_bufp + stop, delta); memmove(xbp->xb_bufp + start + delta, xbp->xb_bufp + start, stop - start); memmove(xbp->xb_bufp + start, buf, delta); done: xo_anchor_clear(xop); } static const char * xo_class_name (int ftype) { switch (ftype) { case 'D': return "decoration"; case 'E': return "error"; case 'L': return "label"; case 'N': return "note"; case 'P': return "padding"; case 'W': return "warning"; } return NULL; } static const char * xo_tag_name (int ftype) { switch (ftype) { case 'E': return "__error"; case 'W': return "__warning"; } return NULL; } static int xo_role_wants_default_format (int ftype) { switch (ftype) { /* These roles can be completely empty and/or without formatting */ case 'C': case 'G': case '[': case ']': return 0; } return 1; } static xo_mapping_t xo_role_names[] = { { 'C', "color" }, { 'D', "decoration" }, { 'E', "error" }, { 'L', "label" }, { 'N', "note" }, { 'P', "padding" }, { 'T', "title" }, { 'U', "units" }, { 'V', "value" }, { 'W', "warning" }, { '[', "start-anchor" }, { ']', "stop-anchor" }, { 0, NULL } }; #define XO_ROLE_EBRACE '{' /* Escaped braces */ #define XO_ROLE_TEXT '+' #define XO_ROLE_NEWLINE '\n' static xo_mapping_t xo_modifier_names[] = { { XFF_ARGUMENT, "argument" }, { XFF_COLON, "colon" }, { XFF_COMMA, "comma" }, { XFF_DISPLAY_ONLY, "display" }, { XFF_ENCODE_ONLY, "encoding" }, { XFF_GT_FIELD, "gettext" }, { XFF_HUMANIZE, "humanize" }, { XFF_HUMANIZE, "hn" }, { XFF_HN_SPACE, "hn-space" }, { XFF_HN_DECIMAL, "hn-decimal" }, { XFF_HN_1000, "hn-1000" }, { XFF_KEY, "key" }, { XFF_LEAF_LIST, "leaf-list" }, { XFF_LEAF_LIST, "list" }, { XFF_NOQUOTE, "no-quotes" }, { XFF_NOQUOTE, "no-quote" }, { XFF_GT_PLURAL, "plural" }, { XFF_QUOTE, "quotes" }, { XFF_QUOTE, "quote" }, { XFF_TRIM_WS, "trim" }, { XFF_WS, "white" }, { 0, NULL } }; #ifdef NOT_NEEDED_YET static xo_mapping_t xo_modifier_short_names[] = { { XFF_COLON, "c" }, { XFF_DISPLAY_ONLY, "d" }, { XFF_ENCODE_ONLY, "e" }, { XFF_GT_FIELD, "g" }, { XFF_HUMANIZE, "h" }, { XFF_KEY, "k" }, { XFF_LEAF_LIST, "l" }, { XFF_NOQUOTE, "n" }, { XFF_GT_PLURAL, "p" }, { XFF_QUOTE, "q" }, { XFF_TRIM_WS, "t" }, { XFF_WS, "w" }, { 0, NULL } }; #endif /* NOT_NEEDED_YET */ static int xo_count_fields (xo_handle_t *xop UNUSED, const char *fmt) { int rc = 1; const char *cp; for (cp = fmt; *cp; cp++) if (*cp == '{' || *cp == '\n') rc += 1; return rc * 2 + 1; } /* * The field format is: * '{' modifiers ':' content [ '/' print-fmt [ '/' encode-fmt ]] '}' * Roles are optional and include the following field types: * 'D': decoration; something non-text and non-data (colons, commmas) * 'E': error message * 'G': gettext() the entire string; optional domainname as content * 'L': label; text preceding data * 'N': note; text following data * 'P': padding; whitespace * 'T': Title, where 'content' is a column title * 'U': Units, where 'content' is the unit label * 'V': value, where 'content' is the name of the field (the default) * 'W': warning message * '[': start a section of anchored text * ']': end a section of anchored text * The following modifiers are also supported: * 'a': content is provided via argument (const char *), not descriptor * 'c': flag: emit a colon after the label * 'd': field is only emitted for display styles (text and html) * 'e': field is only emitted for encoding styles (xml and json) * 'g': gettext() the field * 'h': humanize a numeric value (only for display styles) * 'k': this field is a key, suitable for XPath predicates * 'l': a leaf-list, a simple list of values * 'n': no quotes around this field * 'p': the field has plural gettext semantics (ngettext) * 'q': add quotes around this field * 't': trim whitespace around the value * 'w': emit a blank after the label * The print-fmt and encode-fmt strings is the printf-style formating * for this data. JSON and XML will use the encoding-fmt, if present. * If the encode-fmt is not provided, it defaults to the print-fmt. * If the print-fmt is not provided, it defaults to 's'. */ static const char * xo_parse_roles (xo_handle_t *xop, const char *fmt, const char *basep, xo_field_info_t *xfip) { const char *sp; unsigned ftype = 0; xo_xff_flags_t flags = 0; uint8_t fnum = 0; for (sp = basep; sp && *sp; sp++) { if (*sp == ':' || *sp == '/' || *sp == '}') break; if (*sp == '\\') { if (sp[1] == '\0') { xo_failure(xop, "backslash at the end of string"); return NULL; } /* Anything backslashed is ignored */ sp += 1; continue; } if (*sp == ',') { const char *np; for (np = ++sp; *np; np++) if (*np == ':' || *np == '/' || *np == '}' || *np == ',') break; ssize_t slen = np - sp; if (slen > 0) { xo_xff_flags_t value; value = xo_name_lookup(xo_role_names, sp, slen); if (value) ftype = value; else { value = xo_name_lookup(xo_modifier_names, sp, slen); if (value) flags |= value; else xo_failure(xop, "unknown keyword ignored: '%.*s'", slen, sp); } } sp = np - 1; continue; } switch (*sp) { case 'C': case 'D': case 'E': case 'G': case 'L': case 'N': case 'P': case 'T': case 'U': case 'V': case 'W': case '[': case ']': if (ftype != 0) { xo_failure(xop, "field descriptor uses multiple types: '%s'", xo_printable(fmt)); return NULL; } ftype = *sp; break; case '0': case '1': case '2': case '3': case '4': case '5': case '6': case '7': case '8': case '9': fnum = (fnum * 10) + (*sp - '0'); break; case 'a': flags |= XFF_ARGUMENT; break; case 'c': flags |= XFF_COLON; break; case 'd': flags |= XFF_DISPLAY_ONLY; break; case 'e': flags |= XFF_ENCODE_ONLY; break; case 'g': flags |= XFF_GT_FIELD; break; case 'h': flags |= XFF_HUMANIZE; break; case 'k': flags |= XFF_KEY; break; case 'l': flags |= XFF_LEAF_LIST; break; case 'n': flags |= XFF_NOQUOTE; break; case 'p': flags |= XFF_GT_PLURAL; break; case 'q': flags |= XFF_QUOTE; break; case 't': flags |= XFF_TRIM_WS; break; case 'w': flags |= XFF_WS; break; default: xo_failure(xop, "field descriptor uses unknown modifier: '%s'", xo_printable(fmt)); /* * No good answer here; a bad format will likely * mean a core file. We just return and hope * the caller notices there's no output, and while * that seems, well, bad, there's nothing better. */ return NULL; } if (ftype == 'N' || ftype == 'U') { if (flags & XFF_COLON) { xo_failure(xop, "colon modifier on 'N' or 'U' field ignored: " "'%s'", xo_printable(fmt)); flags &= ~XFF_COLON; } } } xfip->xfi_flags = flags; xfip->xfi_ftype = ftype ?: 'V'; xfip->xfi_fnum = fnum; return sp; } /* * Number any remaining fields that need numbers. Note that some * field types (text, newline, escaped braces) never get numbers. */ static void xo_gettext_finish_numbering_fields (xo_handle_t *xop UNUSED, const char *fmt UNUSED, xo_field_info_t *fields) { xo_field_info_t *xfip; unsigned fnum, max_fields; uint64_t bits = 0; /* First make a list of add the explicitly used bits */ for (xfip = fields, fnum = 0; xfip->xfi_ftype; xfip++) { switch (xfip->xfi_ftype) { case XO_ROLE_NEWLINE: /* Don't get numbered */ case XO_ROLE_TEXT: case XO_ROLE_EBRACE: case 'G': continue; } fnum += 1; if (fnum >= 63) break; if (xfip->xfi_fnum) bits |= 1 << xfip->xfi_fnum; } max_fields = fnum; for (xfip = fields, fnum = 0; xfip->xfi_ftype; xfip++) { switch (xfip->xfi_ftype) { case XO_ROLE_NEWLINE: /* Don't get numbered */ case XO_ROLE_TEXT: case XO_ROLE_EBRACE: case 'G': continue; } if (xfip->xfi_fnum != 0) continue; /* Find the next unassigned field */ for (fnum++; bits & (1 << fnum); fnum++) continue; if (fnum > max_fields) break; xfip->xfi_fnum = fnum; /* Mark the field number */ bits |= 1 << fnum; /* Mark it used */ } } /* * The format string uses field numbers, so we need to whiffle through it * and make sure everything's sane and lovely. */ static int xo_parse_field_numbers (xo_handle_t *xop, const char *fmt, xo_field_info_t *fields, unsigned num_fields) { xo_field_info_t *xfip; unsigned field, fnum; uint64_t bits = 0; for (xfip = fields, field = 0; field < num_fields; xfip++, field++) { /* Fields default to 1:1 with natural position */ if (xfip->xfi_fnum == 0) xfip->xfi_fnum = field + 1; else if (xfip->xfi_fnum > num_fields) { xo_failure(xop, "field number exceeds number of fields: '%s'", fmt); return -1; } fnum = xfip->xfi_fnum - 1; /* Move to zero origin */ if (fnum < 64) { /* Only test what fits */ if (bits & (1 << fnum)) { xo_failure(xop, "field number %u reused: '%s'", xfip->xfi_fnum, fmt); return -1; } bits |= 1 << fnum; } } return 0; } static int xo_parse_fields (xo_handle_t *xop, xo_field_info_t *fields, unsigned num_fields, const char *fmt) { const char *cp, *sp, *ep, *basep; unsigned field = 0; xo_field_info_t *xfip = fields; unsigned seen_fnum = 0; for (cp = fmt; *cp && field < num_fields; field++, xfip++) { xfip->xfi_start = cp; if (*cp == '\n') { xfip->xfi_ftype = XO_ROLE_NEWLINE; xfip->xfi_len = 1; cp += 1; continue; } if (*cp != '{') { /* Normal text */ for (sp = cp; *sp; sp++) { if (*sp == '{' || *sp == '\n') break; } xfip->xfi_ftype = XO_ROLE_TEXT; xfip->xfi_content = cp; xfip->xfi_clen = sp - cp; xfip->xfi_next = sp; cp = sp; continue; } if (cp[1] == '{') { /* Start of {{escaped braces}} */ xfip->xfi_start = cp + 1; /* Start at second brace */ xfip->xfi_ftype = XO_ROLE_EBRACE; cp += 2; /* Skip over _both_ characters */ for (sp = cp; *sp; sp++) { if (*sp == '}' && sp[1] == '}') break; } if (*sp == '\0') { xo_failure(xop, "missing closing '}}': '%s'", xo_printable(fmt)); return -1; } xfip->xfi_len = sp - xfip->xfi_start + 1; /* Move along the string, but don't run off the end */ if (*sp == '}' && sp[1] == '}') sp += 2; cp = *sp ? sp : sp; xfip->xfi_next = cp; continue; } /* We are looking at the start of a field definition */ xfip->xfi_start = basep = cp + 1; const char *format = NULL; ssize_t flen = 0; /* Looking at roles and modifiers */ sp = xo_parse_roles(xop, fmt, basep, xfip); if (sp == NULL) { /* xo_failure has already been called */ return -1; } if (xfip->xfi_fnum) seen_fnum = 1; /* Looking at content */ if (*sp == ':') { for (ep = ++sp; *sp; sp++) { if (*sp == '}' || *sp == '/') break; if (*sp == '\\') { if (sp[1] == '\0') { xo_failure(xop, "backslash at the end of string"); return -1; } sp += 1; continue; } } if (ep != sp) { xfip->xfi_clen = sp - ep; xfip->xfi_content = ep; } } else { xo_failure(xop, "missing content (':'): '%s'", xo_printable(fmt)); return -1; } /* Looking at main (display) format */ if (*sp == '/') { for (ep = ++sp; *sp; sp++) { if (*sp == '}' || *sp == '/') break; if (*sp == '\\') { if (sp[1] == '\0') { xo_failure(xop, "backslash at the end of string"); return -1; } sp += 1; continue; } } flen = sp - ep; format = ep; } /* Looking at encoding format */ if (*sp == '/') { for (ep = ++sp; *sp; sp++) { if (*sp == '}') break; } xfip->xfi_encoding = ep; xfip->xfi_elen = sp - ep; } if (*sp != '}') { xo_failure(xop, "missing closing '}': %s", xo_printable(fmt)); return -1; } xfip->xfi_len = sp - xfip->xfi_start; xfip->xfi_next = ++sp; /* If we have content, then we have a default format */ if (xfip->xfi_clen || format || (xfip->xfi_flags & XFF_ARGUMENT)) { if (format) { xfip->xfi_format = format; xfip->xfi_flen = flen; } else if (xo_role_wants_default_format(xfip->xfi_ftype)) { xfip->xfi_format = xo_default_format; xfip->xfi_flen = 2; } } cp = sp; } int rc = 0; /* * If we saw a field number on at least one field, then we need * to enforce some rules and/or guidelines. */ if (seen_fnum) rc = xo_parse_field_numbers(xop, fmt, fields, field); return rc; } /* * We are passed a pointer to a format string just past the "{G:}" * field. We build a simplified version of the format string. */ static int xo_gettext_simplify_format (xo_handle_t *xop UNUSED, xo_buffer_t *xbp, xo_field_info_t *fields, int this_field, const char *fmt UNUSED, xo_simplify_field_func_t field_cb) { unsigned ftype; xo_xff_flags_t flags; int field = this_field + 1; xo_field_info_t *xfip; char ch; for (xfip = &fields[field]; xfip->xfi_ftype; xfip++, field++) { ftype = xfip->xfi_ftype; flags = xfip->xfi_flags; if ((flags & XFF_GT_FIELD) && xfip->xfi_content && ftype != 'V') { if (field_cb) field_cb(xfip->xfi_content, xfip->xfi_clen, (flags & XFF_GT_PLURAL) ? 1 : 0); } switch (ftype) { case 'G': /* Ignore gettext roles */ break; case XO_ROLE_NEWLINE: xo_buf_append(xbp, "\n", 1); break; case XO_ROLE_EBRACE: xo_buf_append(xbp, "{", 1); xo_buf_append(xbp, xfip->xfi_content, xfip->xfi_clen); xo_buf_append(xbp, "}", 1); break; case XO_ROLE_TEXT: xo_buf_append(xbp, xfip->xfi_content, xfip->xfi_clen); break; default: xo_buf_append(xbp, "{", 1); if (ftype != 'V') { ch = ftype; xo_buf_append(xbp, &ch, 1); } unsigned fnum = xfip->xfi_fnum ?: 0; if (fnum) { char num[12]; /* Field numbers are origin 1, not 0, following printf(3) */ snprintf(num, sizeof(num), "%u", fnum); xo_buf_append(xbp, num, strlen(num)); } xo_buf_append(xbp, ":", 1); xo_buf_append(xbp, xfip->xfi_content, xfip->xfi_clen); xo_buf_append(xbp, "}", 1); } } xo_buf_append(xbp, "", 1); return 0; } void xo_dump_fields (xo_field_info_t *); /* Fake prototype for debug function */ void xo_dump_fields (xo_field_info_t *fields) { xo_field_info_t *xfip; for (xfip = fields; xfip->xfi_ftype; xfip++) { printf("%lu(%u): %lx [%c/%u] [%.*s] [%.*s] [%.*s]\n", (unsigned long) (xfip - fields), xfip->xfi_fnum, (unsigned long) xfip->xfi_flags, isprint((int) xfip->xfi_ftype) ? xfip->xfi_ftype : ' ', xfip->xfi_ftype, (int) xfip->xfi_clen, xfip->xfi_content ?: "", (int) xfip->xfi_flen, xfip->xfi_format ?: "", (int) xfip->xfi_elen, xfip->xfi_encoding ?: ""); } } #ifdef HAVE_GETTEXT /* * Find the field that matches the given field number */ static xo_field_info_t * xo_gettext_find_field (xo_field_info_t *fields, unsigned fnum) { xo_field_info_t *xfip; for (xfip = fields; xfip->xfi_ftype; xfip++) if (xfip->xfi_fnum == fnum) return xfip; return NULL; } /* * At this point, we need to consider if the fields have been reordered, * such as "The {:adjective} {:noun}" to "La {:noun} {:adjective}". * * We need to rewrite the new_fields using the old fields order, * so that we can render the message using the arguments as they * appear on the stack. It's a lot of work, but we don't really * want to (eventually) fall into the standard printf code which * means using the arguments straight (and in order) from the * varargs we were originally passed. */ static void xo_gettext_rewrite_fields (xo_handle_t *xop UNUSED, xo_field_info_t *fields, unsigned max_fields) { xo_field_info_t tmp[max_fields]; bzero(tmp, max_fields * sizeof(tmp[0])); unsigned fnum = 0; xo_field_info_t *newp, *outp, *zp; for (newp = fields, outp = tmp; newp->xfi_ftype; newp++, outp++) { switch (newp->xfi_ftype) { case XO_ROLE_NEWLINE: /* Don't get numbered */ case XO_ROLE_TEXT: case XO_ROLE_EBRACE: case 'G': *outp = *newp; outp->xfi_renum = 0; continue; } zp = xo_gettext_find_field(fields, ++fnum); if (zp == NULL) { /* Should not occur */ *outp = *newp; outp->xfi_renum = 0; continue; } *outp = *zp; outp->xfi_renum = newp->xfi_fnum; } memcpy(fields, tmp, max_fields * sizeof(tmp[0])); } /* * We've got two lists of fields, the old list from the original * format string and the new one from the parsed gettext reply. The * new list has the localized words, where the old list has the * formatting information. We need to combine them into a single list * (the new list). * * If the list needs to be reordered, then we've got more serious work * to do. */ static int xo_gettext_combine_formats (xo_handle_t *xop, const char *fmt UNUSED, const char *gtfmt, xo_field_info_t *old_fields, xo_field_info_t *new_fields, unsigned new_max_fields, int *reorderedp) { int reordered = 0; xo_field_info_t *newp, *oldp, *startp = old_fields; xo_gettext_finish_numbering_fields(xop, fmt, old_fields); for (newp = new_fields; newp->xfi_ftype; newp++) { switch (newp->xfi_ftype) { case XO_ROLE_NEWLINE: case XO_ROLE_TEXT: case XO_ROLE_EBRACE: continue; case 'V': for (oldp = startp; oldp->xfi_ftype; oldp++) { if (oldp->xfi_ftype != 'V') continue; if (newp->xfi_clen != oldp->xfi_clen || strncmp(newp->xfi_content, oldp->xfi_content, oldp->xfi_clen) != 0) { reordered = 1; continue; } startp = oldp + 1; break; } /* Didn't find it on the first pass (starting from start) */ if (oldp->xfi_ftype == 0) { for (oldp = old_fields; oldp < startp; oldp++) { if (oldp->xfi_ftype != 'V') continue; if (newp->xfi_clen != oldp->xfi_clen) continue; if (strncmp(newp->xfi_content, oldp->xfi_content, oldp->xfi_clen) != 0) continue; reordered = 1; break; } if (oldp == startp) { /* Field not found */ xo_failure(xop, "post-gettext format can't find field " "'%.*s' in format '%s'", newp->xfi_clen, newp->xfi_content, xo_printable(gtfmt)); return -1; } } break; default: /* * Other fields don't have names for us to use, so if * the types aren't the same, then we'll have to assume * the original field is a match. */ for (oldp = startp; oldp->xfi_ftype; oldp++) { if (oldp->xfi_ftype == 'V') /* Can't go past these */ break; if (oldp->xfi_ftype == newp->xfi_ftype) goto copy_it; /* Assumably we have a match */ } continue; } /* * Found a match; copy over appropriate fields */ copy_it: newp->xfi_flags = oldp->xfi_flags; newp->xfi_fnum = oldp->xfi_fnum; newp->xfi_format = oldp->xfi_format; newp->xfi_flen = oldp->xfi_flen; newp->xfi_encoding = oldp->xfi_encoding; newp->xfi_elen = oldp->xfi_elen; } *reorderedp = reordered; if (reordered) { xo_gettext_finish_numbering_fields(xop, fmt, new_fields); xo_gettext_rewrite_fields(xop, new_fields, new_max_fields); } return 0; } /* * We don't want to make gettext() calls here with a complete format * string, since that means changing a flag would mean a * labor-intensive re-translation expense. Instead we build a * simplified form with a reduced level of detail, perform a lookup on * that string and then re-insert the formating info. * * So something like: * xo_emit("{G:}close {:fd/%ld} returned {g:error/%m} {:test/%6.6s}\n", ...) * would have a lookup string of: * "close {:fd} returned {:error} {:test}\n" * * We also need to handling reordering of fields, where the gettext() * reply string uses fields in a different order than the original * format string: * "cluse-a {:fd} retoorned {:test}. Bork {:error} Bork. Bork.\n" * If we have to reorder fields within the message, then things get * complicated. See xo_gettext_rewrite_fields. * * Summary: i18n aighn't cheap. */ static const char * xo_gettext_build_format (xo_handle_t *xop, xo_field_info_t *fields, int this_field, const char *fmt, char **new_fmtp) { if (xo_style_is_encoding(xop)) goto bail; xo_buffer_t xb; xo_buf_init(&xb); if (xo_gettext_simplify_format(xop, &xb, fields, this_field, fmt, NULL)) goto bail2; const char *gtfmt = xo_dgettext(xop, xb.xb_bufp); if (gtfmt == NULL || gtfmt == fmt || strcmp(gtfmt, fmt) == 0) goto bail2; char *new_fmt = xo_strndup(gtfmt, -1); if (new_fmt == NULL) goto bail2; xo_buf_cleanup(&xb); *new_fmtp = new_fmt; return new_fmt; bail2: xo_buf_cleanup(&xb); bail: *new_fmtp = NULL; return fmt; } static void xo_gettext_rebuild_content (xo_handle_t *xop, xo_field_info_t *fields, ssize_t *fstart, unsigned min_fstart, ssize_t *fend, unsigned max_fend) { xo_field_info_t *xfip; char *buf; ssize_t base = fstart[min_fstart]; ssize_t blen = fend[max_fend] - base; xo_buffer_t *xbp = &xop->xo_data; if (blen == 0) return; buf = xo_realloc(NULL, blen); if (buf == NULL) return; memcpy(buf, xbp->xb_bufp + fstart[min_fstart], blen); /* Copy our data */ unsigned field = min_fstart, len, fnum; ssize_t soff, doff = base; xo_field_info_t *zp; /* * Be aware there are two competing views of "field number": we * want the user to thing in terms of "The {1:size}" where {G:}, * newlines, escaped braces, and text don't have numbers. But is * also the internal view, where we have an array of * xo_field_info_t and every field have an index. fnum, fstart[] * and fend[] are the latter, but xfi_renum is the former. */ for (xfip = fields + field; xfip->xfi_ftype; xfip++, field++) { fnum = field; if (xfip->xfi_renum) { zp = xo_gettext_find_field(fields, xfip->xfi_renum); fnum = zp ? zp - fields : field; } soff = fstart[fnum]; len = fend[fnum] - soff; if (len > 0) { soff -= base; memcpy(xbp->xb_bufp + doff, buf + soff, len); doff += len; } } xo_free(buf); } #else /* HAVE_GETTEXT */ static const char * xo_gettext_build_format (xo_handle_t *xop UNUSED, xo_field_info_t *fields UNUSED, int this_field UNUSED, const char *fmt UNUSED, char **new_fmtp) { *new_fmtp = NULL; return fmt; } static int xo_gettext_combine_formats (xo_handle_t *xop UNUSED, const char *fmt UNUSED, const char *gtfmt UNUSED, xo_field_info_t *old_fields UNUSED, xo_field_info_t *new_fields UNUSED, unsigned new_max_fields UNUSED, int *reorderedp UNUSED) { return -1; } static void xo_gettext_rebuild_content (xo_handle_t *xop UNUSED, xo_field_info_t *fields UNUSED, ssize_t *fstart UNUSED, unsigned min_fstart UNUSED, ssize_t *fend UNUSED, unsigned max_fend UNUSED) { return; } #endif /* HAVE_GETTEXT */ /* * Emit a set of fields. This is really the core of libxo. */ static ssize_t xo_do_emit_fields (xo_handle_t *xop, xo_field_info_t *fields, unsigned max_fields, const char *fmt) { int gettext_inuse = 0; int gettext_changed = 0; int gettext_reordered = 0; unsigned ftype; xo_xff_flags_t flags; xo_field_info_t *new_fields = NULL; xo_field_info_t *xfip; unsigned field; ssize_t rc = 0; int flush = XOF_ISSET(xop, XOF_FLUSH); int flush_line = XOF_ISSET(xop, XOF_FLUSH_LINE); char *new_fmt = NULL; if (XOIF_ISSET(xop, XOIF_REORDER) || xo_style(xop) == XO_STYLE_ENCODER) flush_line = 0; /* * Some overhead for gettext; if the fields in the msgstr returned * by gettext are reordered, then we need to record start and end * for each field. We'll go ahead and render the fields in the * normal order, but later we can then reconstruct the reordered * fields using these fstart/fend values. */ unsigned flimit = max_fields * 2; /* Pessimistic limit */ unsigned min_fstart = flimit - 1; unsigned max_fend = 0; /* Highest recorded fend[] entry */ ssize_t fstart[flimit]; bzero(fstart, flimit * sizeof(fstart[0])); ssize_t fend[flimit]; bzero(fend, flimit * sizeof(fend[0])); for (xfip = fields, field = 0; field < max_fields && xfip->xfi_ftype; xfip++, field++) { ftype = xfip->xfi_ftype; flags = xfip->xfi_flags; /* Record field start offset */ if (gettext_reordered) { fstart[field] = xo_buf_offset(&xop->xo_data); if (min_fstart > field) min_fstart = field; } const char *content = xfip->xfi_content; ssize_t clen = xfip->xfi_clen; if (flags & XFF_ARGUMENT) { /* * Argument flag means the content isn't given in the descriptor, * but as a UTF-8 string ('const char *') argument in xo_vap. */ content = va_arg(xop->xo_vap, char *); clen = content ? strlen(content) : 0; } if (ftype == XO_ROLE_NEWLINE) { xo_line_close(xop); if (flush_line && xo_flush_h(xop) < 0) return -1; goto bottom; } else if (ftype == XO_ROLE_EBRACE) { xo_format_text(xop, xfip->xfi_start, xfip->xfi_len); goto bottom; } else if (ftype == XO_ROLE_TEXT) { /* Normal text */ xo_format_text(xop, xfip->xfi_content, xfip->xfi_clen); goto bottom; } /* * Notes and units need the 'w' flag handled before the content. */ if (ftype == 'N' || ftype == 'U') { if (flags & XFF_WS) { xo_format_content(xop, "padding", NULL, " ", 1, NULL, 0, flags); flags &= ~XFF_WS; /* Prevent later handling of this flag */ } } if (ftype == 'V') xo_format_value(xop, content, clen, NULL, 0, xfip->xfi_format, xfip->xfi_flen, xfip->xfi_encoding, xfip->xfi_elen, flags); else if (ftype == '[') xo_anchor_start(xop, xfip, content, clen); else if (ftype == ']') xo_anchor_stop(xop, xfip, content, clen); else if (ftype == 'C') xo_format_colors(xop, xfip, content, clen); else if (ftype == 'G') { /* * A {G:domain} field; disect the domain name and translate * the remaining portion of the input string. If the user * didn't put the {G:} at the start of the format string, then * assumably they just want us to translate the rest of it. * Since gettext returns strings in a static buffer, we make * a copy in new_fmt. */ xo_set_gettext_domain(xop, xfip, content, clen); if (!gettext_inuse) { /* Only translate once */ gettext_inuse = 1; if (new_fmt) { xo_free(new_fmt); new_fmt = NULL; } xo_gettext_build_format(xop, fields, field, xfip->xfi_next, &new_fmt); if (new_fmt) { gettext_changed = 1; unsigned new_max_fields = xo_count_fields(xop, new_fmt); if (++new_max_fields < max_fields) new_max_fields = max_fields; /* Leave a blank slot at the beginning */ ssize_t sz = (new_max_fields + 1) * sizeof(xo_field_info_t); new_fields = alloca(sz); bzero(new_fields, sz); if (!xo_parse_fields(xop, new_fields + 1, new_max_fields, new_fmt)) { gettext_reordered = 0; if (!xo_gettext_combine_formats(xop, fmt, new_fmt, fields, new_fields + 1, new_max_fields, &gettext_reordered)) { if (gettext_reordered) { if (XOF_ISSET(xop, XOF_LOG_GETTEXT)) xo_failure(xop, "gettext finds reordered " "fields in '%s' and '%s'", xo_printable(fmt), xo_printable(new_fmt)); flush_line = 0; /* Must keep at content */ XOIF_SET(xop, XOIF_REORDER); } field = -1; /* Will be incremented at top of loop */ xfip = new_fields; max_fields = new_max_fields; } } } } continue; } else if (clen || xfip->xfi_format) { const char *class_name = xo_class_name(ftype); if (class_name) xo_format_content(xop, class_name, xo_tag_name(ftype), content, clen, xfip->xfi_format, xfip->xfi_flen, flags); else if (ftype == 'T') xo_format_title(xop, xfip, content, clen); else if (ftype == 'U') xo_format_units(xop, xfip, content, clen); else xo_failure(xop, "unknown field type: '%c'", ftype); } if (flags & XFF_COLON) xo_format_content(xop, "decoration", NULL, ":", 1, NULL, 0, 0); if (flags & XFF_WS) xo_format_content(xop, "padding", NULL, " ", 1, NULL, 0, 0); bottom: /* Record the end-of-field offset */ if (gettext_reordered) { fend[field] = xo_buf_offset(&xop->xo_data); max_fend = field; } } if (gettext_changed && gettext_reordered) { /* Final step: rebuild the content using the rendered fields */ xo_gettext_rebuild_content(xop, new_fields + 1, fstart, min_fstart, fend, max_fend); } XOIF_CLEAR(xop, XOIF_REORDER); /* * If we've got enough data, flush it. */ if (xo_buf_offset(&xop->xo_data) > XO_BUF_HIGH_WATER) flush = 1; /* If we don't have an anchor, write the text out */ if (flush && !XOIF_ISSET(xop, XOIF_ANCHOR)) { if (xo_write(xop) < 0) rc = -1; /* Report failure */ else if (xo_flush_h(xop) < 0) rc = -1; } if (new_fmt) xo_free(new_fmt); /* * We've carried the gettext domainname inside our handle just for * convenience, but we need to ensure it doesn't survive across * xo_emit calls. */ if (xop->xo_gt_domain) { xo_free(xop->xo_gt_domain); xop->xo_gt_domain = NULL; } return (rc < 0) ? rc : xop->xo_columns; } /* * Parse and emit a set of fields */ static int xo_do_emit (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt) { xop->xo_columns = 0; /* Always reset it */ xop->xo_errno = errno; /* Save for "%m" */ if (fmt == NULL) return 0; unsigned max_fields; xo_field_info_t *fields = NULL; /* Adjust XOEF_RETAIN based on global flags */ if (XOF_ISSET(xop, XOF_RETAIN_ALL)) flags |= XOEF_RETAIN; if (XOF_ISSET(xop, XOF_RETAIN_NONE)) flags &= ~XOEF_RETAIN; /* * Check for 'retain' flag, telling us to retain the field * information. If we've already saved it, then we can avoid * re-parsing the format string. */ if (!(flags & XOEF_RETAIN) || xo_retain_find(fmt, &fields, &max_fields) != 0 || fields == NULL) { /* Nothing retained; parse the format string */ max_fields = xo_count_fields(xop, fmt); fields = alloca(max_fields * sizeof(fields[0])); bzero(fields, max_fields * sizeof(fields[0])); if (xo_parse_fields(xop, fields, max_fields, fmt)) return -1; /* Warning already displayed */ if (flags & XOEF_RETAIN) { /* Retain the info */ xo_retain_add(fmt, fields, max_fields); } } return xo_do_emit_fields(xop, fields, max_fields, fmt); } /* * Rebuild a format string in a gettext-friendly format. This function * is exposed to tools can perform this function. See xo(1). */ char * xo_simplify_format (xo_handle_t *xop, const char *fmt, int with_numbers, xo_simplify_field_func_t field_cb) { xop = xo_default(xop); xop->xo_columns = 0; /* Always reset it */ xop->xo_errno = errno; /* Save for "%m" */ unsigned max_fields = xo_count_fields(xop, fmt); xo_field_info_t fields[max_fields]; bzero(fields, max_fields * sizeof(fields[0])); if (xo_parse_fields(xop, fields, max_fields, fmt)) return NULL; /* Warning already displayed */ xo_buffer_t xb; xo_buf_init(&xb); if (with_numbers) xo_gettext_finish_numbering_fields(xop, fmt, fields); if (xo_gettext_simplify_format(xop, &xb, fields, -1, fmt, field_cb)) return NULL; return xb.xb_bufp; } xo_ssize_t xo_emit_hv (xo_handle_t *xop, const char *fmt, va_list vap) { ssize_t rc; xop = xo_default(xop); va_copy(xop->xo_vap, vap); rc = xo_do_emit(xop, 0, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } xo_ssize_t xo_emit_h (xo_handle_t *xop, const char *fmt, ...) { ssize_t rc; xop = xo_default(xop); va_start(xop->xo_vap, fmt); rc = xo_do_emit(xop, 0, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } xo_ssize_t xo_emit (const char *fmt, ...) { xo_handle_t *xop = xo_default(NULL); ssize_t rc; va_start(xop->xo_vap, fmt); rc = xo_do_emit(xop, 0, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } xo_ssize_t xo_emit_hvf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, va_list vap) { ssize_t rc; xop = xo_default(xop); va_copy(xop->xo_vap, vap); rc = xo_do_emit(xop, flags, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } xo_ssize_t xo_emit_hf (xo_handle_t *xop, xo_emit_flags_t flags, const char *fmt, ...) { ssize_t rc; xop = xo_default(xop); va_start(xop->xo_vap, fmt); rc = xo_do_emit(xop, flags, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } xo_ssize_t xo_emit_f (xo_emit_flags_t flags, const char *fmt, ...) { xo_handle_t *xop = xo_default(NULL); ssize_t rc; va_start(xop->xo_vap, fmt); rc = xo_do_emit(xop, flags, fmt); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); return rc; } /* * Emit a single field by providing the info information typically provided * inside the field description (role, modifiers, and formats). This is * a convenience function to avoid callers using snprintf to build field * descriptions. */ xo_ssize_t xo_emit_field_hv (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, va_list vap) { ssize_t rc; xop = xo_default(xop); if (rolmod == NULL) rolmod = "V"; xo_field_info_t xfi; bzero(&xfi, sizeof(xfi)); const char *cp; cp = xo_parse_roles(xop, rolmod, rolmod, &xfi); if (cp == NULL) return -1; xfi.xfi_start = fmt; xfi.xfi_content = contents; xfi.xfi_format = fmt; xfi.xfi_encoding = efmt; xfi.xfi_clen = contents ? strlen(contents) : 0; xfi.xfi_flen = fmt ? strlen(fmt) : 0; xfi.xfi_elen = efmt ? strlen(efmt) : 0; /* If we have content, then we have a default format */ if (contents && fmt == NULL && xo_role_wants_default_format(xfi.xfi_ftype)) { xfi.xfi_format = xo_default_format; xfi.xfi_flen = 2; } va_copy(xop->xo_vap, vap); rc = xo_do_emit_fields(xop, &xfi, 1, fmt ?: contents ?: "field"); va_end(xop->xo_vap); return rc; } xo_ssize_t xo_emit_field_h (xo_handle_t *xop, const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...) { ssize_t rc; va_list vap; va_start(vap, efmt); rc = xo_emit_field_hv(xop, rolmod, contents, fmt, efmt, vap); va_end(vap); return rc; } xo_ssize_t xo_emit_field (const char *rolmod, const char *contents, const char *fmt, const char *efmt, ...) { ssize_t rc; va_list vap; va_start(vap, efmt); rc = xo_emit_field_hv(NULL, rolmod, contents, fmt, efmt, vap); va_end(vap); return rc; } xo_ssize_t xo_attr_hv (xo_handle_t *xop, const char *name, const char *fmt, va_list vap) { const ssize_t extra = 5; /* space, equals, quote, quote, and nul */ xop = xo_default(xop); ssize_t rc = 0; ssize_t nlen = strlen(name); xo_buffer_t *xbp = &xop->xo_attrs; ssize_t name_offset, value_offset; switch (xo_style(xop)) { case XO_STYLE_XML: if (!xo_buf_has_room(xbp, nlen + extra)) return -1; *xbp->xb_curp++ = ' '; memcpy(xbp->xb_curp, name, nlen); xbp->xb_curp += nlen; *xbp->xb_curp++ = '='; *xbp->xb_curp++ = '"'; rc = xo_vsnprintf(xop, xbp, fmt, vap); if (rc >= 0) { rc = xo_escape_xml(xbp, rc, 1); xbp->xb_curp += rc; } if (!xo_buf_has_room(xbp, 2)) return -1; *xbp->xb_curp++ = '"'; *xbp->xb_curp = '\0'; rc += nlen + extra; break; case XO_STYLE_ENCODER: name_offset = xo_buf_offset(xbp); xo_buf_append(xbp, name, nlen); xo_buf_append(xbp, "", 1); value_offset = xo_buf_offset(xbp); rc = xo_vsnprintf(xop, xbp, fmt, vap); if (rc >= 0) { xbp->xb_curp += rc; *xbp->xb_curp = '\0'; rc = xo_encoder_handle(xop, XO_OP_ATTRIBUTE, xo_buf_data(xbp, name_offset), xo_buf_data(xbp, value_offset), 0); } } return rc; } xo_ssize_t xo_attr_h (xo_handle_t *xop, const char *name, const char *fmt, ...) { ssize_t rc; va_list vap; va_start(vap, fmt); rc = xo_attr_hv(xop, name, fmt, vap); va_end(vap); return rc; } xo_ssize_t xo_attr (const char *name, const char *fmt, ...) { ssize_t rc; va_list vap; va_start(vap, fmt); rc = xo_attr_hv(NULL, name, fmt, vap); va_end(vap); return rc; } static void xo_stack_set_flags (xo_handle_t *xop) { if (XOF_ISSET(xop, XOF_NOT_FIRST)) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; xsp->xs_flags |= XSF_NOT_FIRST; XOF_CLEAR(xop, XOF_NOT_FIRST); } } static void xo_depth_change (xo_handle_t *xop, const char *name, int delta, int indent, xo_state_t state, xo_xsf_flags_t flags) { if (xo_style(xop) == XO_STYLE_HTML || xo_style(xop) == XO_STYLE_TEXT) indent = 0; if (XOF_ISSET(xop, XOF_DTRT)) flags |= XSF_DTRT; if (delta >= 0) { /* Push operation */ if (xo_depth_check(xop, xop->xo_depth + delta)) return; xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth + delta]; xsp->xs_flags = flags; xsp->xs_state = state; xo_stack_set_flags(xop); if (name == NULL) name = XO_FAILURE_NAME; xsp->xs_name = xo_strndup(name, -1); } else { /* Pop operation */ if (xop->xo_depth == 0) { if (!XOF_ISSET(xop, XOF_IGNORE_CLOSE)) xo_failure(xop, "close with empty stack: '%s'", name); return; } xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; if (XOF_ISSET(xop, XOF_WARN)) { const char *top = xsp->xs_name; if (top != NULL && name != NULL && strcmp(name, top) != 0) { xo_failure(xop, "incorrect close: '%s' .vs. '%s'", name, top); return; } if ((xsp->xs_flags & XSF_LIST) != (flags & XSF_LIST)) { xo_failure(xop, "list close on list confict: '%s'", name); return; } if ((xsp->xs_flags & XSF_INSTANCE) != (flags & XSF_INSTANCE)) { xo_failure(xop, "list close on instance confict: '%s'", name); return; } } if (xsp->xs_name) { xo_free(xsp->xs_name); xsp->xs_name = NULL; } if (xsp->xs_keys) { xo_free(xsp->xs_keys); xsp->xs_keys = NULL; } } xop->xo_depth += delta; /* Record new depth */ xop->xo_indent += indent; } void xo_set_depth (xo_handle_t *xop, int depth) { xop = xo_default(xop); if (xo_depth_check(xop, depth)) return; xop->xo_depth += depth; xop->xo_indent += depth; } static xo_xsf_flags_t xo_stack_flags (xo_xof_flags_t xflags) { if (xflags & XOF_DTRT) return XSF_DTRT; return 0; } static void xo_emit_top (xo_handle_t *xop, const char *ppn) { xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn); XOIF_SET(xop, XOIF_TOP_EMITTED); if (xop->xo_version) { xo_printf(xop, "%*s\"__version\": \"%s\", %s", xo_indent(xop), "", xop->xo_version, ppn); xo_free(xop->xo_version); xop->xo_version = NULL; } } static ssize_t xo_do_open_container (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) { ssize_t rc = 0; const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; if (name == NULL) { xo_failure(xop, "NULL passed for container name"); name = XO_FAILURE_NAME; } flags |= xop->xo_flags; /* Pick up handle flags */ switch (xo_style(xop)) { case XO_STYLE_XML: rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name); if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) { rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp; xo_data_append(xop, xop->xo_attrs.xb_bufp, xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp); xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp; } rc += xo_printf(xop, ">%s", ppn); break; case XO_STYLE_JSON: xo_stack_set_flags(xop); if (!XOF_ISSET(xop, XOF_NO_TOP) && !XOIF_ISSET(xop, XOIF_TOP_EMITTED)) xo_emit_top(xop, ppn); if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", "; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; rc = xo_printf(xop, "%s%*s\"%s\": {%s", pre_nl, xo_indent(xop), "", name, ppn); break; case XO_STYLE_SDPARAMS: break; case XO_STYLE_ENCODER: rc = xo_encoder_handle(xop, XO_OP_OPEN_CONTAINER, name, NULL, flags); break; } xo_depth_change(xop, name, 1, 1, XSS_OPEN_CONTAINER, xo_stack_flags(flags)); return rc; } static int xo_open_container_hf (xo_handle_t *xop, xo_xof_flags_t flags, const char *name) { return xo_transition(xop, flags, name, XSS_OPEN_CONTAINER); } xo_ssize_t xo_open_container_h (xo_handle_t *xop, const char *name) { return xo_open_container_hf(xop, 0, name); } xo_ssize_t xo_open_container (const char *name) { return xo_open_container_hf(NULL, 0, name); } xo_ssize_t xo_open_container_hd (xo_handle_t *xop, const char *name) { return xo_open_container_hf(xop, XOF_DTRT, name); } xo_ssize_t xo_open_container_d (const char *name) { return xo_open_container_hf(NULL, XOF_DTRT, name); } static int xo_do_close_container (xo_handle_t *xop, const char *name) { xop = xo_default(xop); ssize_t rc = 0; const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; name = xsp->xs_name; if (name) { ssize_t len = strlen(name) + 1; /* We need to make a local copy; xo_depth_change will free it */ char *cp = alloca(len); memcpy(cp, name, len); name = cp; } else if (!(xsp->xs_flags & XSF_DTRT)) { xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; } } switch (xo_style(xop)) { case XO_STYLE_XML: xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0); rc = xo_printf(xop, "%*s%s", xo_indent(xop), "", name, ppn); break; case XO_STYLE_JSON: pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; ppn = (xop->xo_depth <= 1) ? "\n" : ""; xo_depth_change(xop, name, -1, -1, XSS_CLOSE_CONTAINER, 0); rc = xo_printf(xop, "%s%*s}%s", pre_nl, xo_indent(xop), "", ppn); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_HTML: case XO_STYLE_TEXT: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_CONTAINER, 0); break; case XO_STYLE_SDPARAMS: break; case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_CONTAINER, 0); rc = xo_encoder_handle(xop, XO_OP_CLOSE_CONTAINER, name, NULL, 0); break; } return rc; } xo_ssize_t xo_close_container_h (xo_handle_t *xop, const char *name) { return xo_transition(xop, 0, name, XSS_CLOSE_CONTAINER); } xo_ssize_t xo_close_container (const char *name) { return xo_close_container_h(NULL, name); } xo_ssize_t xo_close_container_hd (xo_handle_t *xop) { return xo_close_container_h(xop, NULL); } xo_ssize_t xo_close_container_d (void) { return xo_close_container_h(NULL, NULL); } static int xo_do_open_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { ssize_t rc = 0; int indent = 0; xop = xo_default(xop); const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; switch (xo_style(xop)) { case XO_STYLE_JSON: indent = 1; if (!XOF_ISSET(xop, XOF_NO_TOP) && !XOIF_ISSET(xop, XOIF_TOP_EMITTED)) xo_emit_top(xop, ppn); if (name == NULL) { xo_failure(xop, "NULL passed for list name"); name = XO_FAILURE_NAME; } xo_stack_set_flags(xop); if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", "; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; rc = xo_printf(xop, "%s%*s\"%s\": [%s", pre_nl, xo_indent(xop), "", name, ppn); break; case XO_STYLE_ENCODER: rc = xo_encoder_handle(xop, XO_OP_OPEN_LIST, name, NULL, flags); break; } xo_depth_change(xop, name, 1, indent, XSS_OPEN_LIST, XSF_LIST | xo_stack_flags(flags)); return rc; } static int xo_open_list_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { return xo_transition(xop, flags, name, XSS_OPEN_LIST); } xo_ssize_t xo_open_list_h (xo_handle_t *xop, const char *name) { return xo_open_list_hf(xop, 0, name); } xo_ssize_t xo_open_list (const char *name) { return xo_open_list_hf(NULL, 0, name); } xo_ssize_t xo_open_list_hd (xo_handle_t *xop, const char *name) { return xo_open_list_hf(xop, XOF_DTRT, name); } xo_ssize_t xo_open_list_d (const char *name) { return xo_open_list_hf(NULL, XOF_DTRT, name); } static int xo_do_close_list (xo_handle_t *xop, const char *name) { ssize_t rc = 0; const char *pre_nl = ""; if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; name = xsp->xs_name; if (name) { ssize_t len = strlen(name) + 1; /* We need to make a local copy; xo_depth_change will free it */ char *cp = alloca(len); memcpy(cp, name, len); name = cp; } else if (!(xsp->xs_flags & XSF_DTRT)) { xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; } } switch (xo_style(xop)) { case XO_STYLE_JSON: if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LIST, XSF_LIST); rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), ""); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LIST, XSF_LIST); rc = xo_encoder_handle(xop, XO_OP_CLOSE_LIST, name, NULL, 0); break; default: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LIST, XSF_LIST); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; } return rc; } xo_ssize_t xo_close_list_h (xo_handle_t *xop, const char *name) { return xo_transition(xop, 0, name, XSS_CLOSE_LIST); } xo_ssize_t xo_close_list (const char *name) { return xo_close_list_h(NULL, name); } xo_ssize_t xo_close_list_hd (xo_handle_t *xop) { return xo_close_list_h(xop, NULL); } xo_ssize_t xo_close_list_d (void) { return xo_close_list_h(NULL, NULL); } static int xo_do_open_leaf_list (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { ssize_t rc = 0; int indent = 0; xop = xo_default(xop); const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; switch (xo_style(xop)) { case XO_STYLE_JSON: indent = 1; if (!XOF_ISSET(xop, XOF_NO_TOP)) { if (!XOIF_ISSET(xop, XOIF_TOP_EMITTED)) { xo_printf(xop, "%*s{%s", xo_indent(xop), "", ppn); XOIF_SET(xop, XOIF_TOP_EMITTED); } } if (name == NULL) { xo_failure(xop, "NULL passed for list name"); name = XO_FAILURE_NAME; } xo_stack_set_flags(xop); if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", "; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; rc = xo_printf(xop, "%s%*s\"%s\": [%s", pre_nl, xo_indent(xop), "", name, ppn); break; case XO_STYLE_ENCODER: rc = xo_encoder_handle(xop, XO_OP_OPEN_LEAF_LIST, name, NULL, flags); break; } xo_depth_change(xop, name, 1, indent, XSS_OPEN_LEAF_LIST, XSF_LIST | xo_stack_flags(flags)); return rc; } static int xo_do_close_leaf_list (xo_handle_t *xop, const char *name) { ssize_t rc = 0; const char *pre_nl = ""; if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; name = xsp->xs_name; if (name) { ssize_t len = strlen(name) + 1; /* We need to make a local copy; xo_depth_change will free it */ char *cp = alloca(len); memcpy(cp, name, len); name = cp; } else if (!(xsp->xs_flags & XSF_DTRT)) { xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; } } switch (xo_style(xop)) { case XO_STYLE_JSON: if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; xo_depth_change(xop, name, -1, -1, XSS_CLOSE_LEAF_LIST, XSF_LIST); rc = xo_printf(xop, "%s%*s]", pre_nl, xo_indent(xop), ""); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_ENCODER: rc = xo_encoder_handle(xop, XO_OP_CLOSE_LEAF_LIST, name, NULL, 0); /* FALLTHRU */ default: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_LEAF_LIST, XSF_LIST); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; } return rc; } static int xo_do_open_instance (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { xop = xo_default(xop); ssize_t rc = 0; const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; flags |= xop->xo_flags; if (name == NULL) { xo_failure(xop, "NULL passed for instance name"); name = XO_FAILURE_NAME; } switch (xo_style(xop)) { case XO_STYLE_XML: rc = xo_printf(xop, "%*s<%s", xo_indent(xop), "", name); if (xop->xo_attrs.xb_curp != xop->xo_attrs.xb_bufp) { rc += xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp; xo_data_append(xop, xop->xo_attrs.xb_bufp, xop->xo_attrs.xb_curp - xop->xo_attrs.xb_bufp); xop->xo_attrs.xb_curp = xop->xo_attrs.xb_bufp; } rc += xo_printf(xop, ">%s", ppn); break; case XO_STYLE_JSON: xo_stack_set_flags(xop); if (xop->xo_stack[xop->xo_depth].xs_flags & XSF_NOT_FIRST) pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? ",\n" : ", "; xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; rc = xo_printf(xop, "%s%*s{%s", pre_nl, xo_indent(xop), "", ppn); break; case XO_STYLE_SDPARAMS: break; case XO_STYLE_ENCODER: rc = xo_encoder_handle(xop, XO_OP_OPEN_INSTANCE, name, NULL, flags); break; } xo_depth_change(xop, name, 1, 1, XSS_OPEN_INSTANCE, xo_stack_flags(flags)); return rc; } static int xo_open_instance_hf (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name) { return xo_transition(xop, flags, name, XSS_OPEN_INSTANCE); } xo_ssize_t xo_open_instance_h (xo_handle_t *xop, const char *name) { return xo_open_instance_hf(xop, 0, name); } xo_ssize_t xo_open_instance (const char *name) { return xo_open_instance_hf(NULL, 0, name); } xo_ssize_t xo_open_instance_hd (xo_handle_t *xop, const char *name) { return xo_open_instance_hf(xop, XOF_DTRT, name); } xo_ssize_t xo_open_instance_d (const char *name) { return xo_open_instance_hf(NULL, XOF_DTRT, name); } static int xo_do_close_instance (xo_handle_t *xop, const char *name) { xop = xo_default(xop); ssize_t rc = 0; const char *ppn = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; const char *pre_nl = ""; if (name == NULL) { xo_stack_t *xsp = &xop->xo_stack[xop->xo_depth]; name = xsp->xs_name; if (name) { ssize_t len = strlen(name) + 1; /* We need to make a local copy; xo_depth_change will free it */ char *cp = alloca(len); memcpy(cp, name, len); name = cp; } else if (!(xsp->xs_flags & XSF_DTRT)) { xo_failure(xop, "missing name without 'dtrt' mode"); name = XO_FAILURE_NAME; } } switch (xo_style(xop)) { case XO_STYLE_XML: xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0); rc = xo_printf(xop, "%*s%s", xo_indent(xop), "", name, ppn); break; case XO_STYLE_JSON: pre_nl = XOF_ISSET(xop, XOF_PRETTY) ? "\n" : ""; xo_depth_change(xop, name, -1, -1, XSS_CLOSE_INSTANCE, 0); rc = xo_printf(xop, "%s%*s}", pre_nl, xo_indent(xop), ""); xop->xo_stack[xop->xo_depth].xs_flags |= XSF_NOT_FIRST; break; case XO_STYLE_HTML: case XO_STYLE_TEXT: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_INSTANCE, 0); break; case XO_STYLE_SDPARAMS: break; case XO_STYLE_ENCODER: xo_depth_change(xop, name, -1, 0, XSS_CLOSE_INSTANCE, 0); rc = xo_encoder_handle(xop, XO_OP_CLOSE_INSTANCE, name, NULL, 0); break; } return rc; } xo_ssize_t xo_close_instance_h (xo_handle_t *xop, const char *name) { return xo_transition(xop, 0, name, XSS_CLOSE_INSTANCE); } xo_ssize_t xo_close_instance (const char *name) { return xo_close_instance_h(NULL, name); } xo_ssize_t xo_close_instance_hd (xo_handle_t *xop) { return xo_close_instance_h(xop, NULL); } xo_ssize_t xo_close_instance_d (void) { return xo_close_instance_h(NULL, NULL); } static int xo_do_close_all (xo_handle_t *xop, xo_stack_t *limit) { xo_stack_t *xsp; ssize_t rc = 0; xo_xsf_flags_t flags; for (xsp = &xop->xo_stack[xop->xo_depth]; xsp >= limit; xsp--) { switch (xsp->xs_state) { case XSS_INIT: /* Nothing */ rc = 0; break; case XSS_OPEN_CONTAINER: rc = xo_do_close_container(xop, NULL); break; case XSS_OPEN_LIST: rc = xo_do_close_list(xop, NULL); break; case XSS_OPEN_INSTANCE: rc = xo_do_close_instance(xop, NULL); break; case XSS_OPEN_LEAF_LIST: rc = xo_do_close_leaf_list(xop, NULL); break; case XSS_MARKER: flags = xsp->xs_flags & XSF_MARKER_FLAGS; xo_depth_change(xop, xsp->xs_name, -1, 0, XSS_MARKER, 0); xop->xo_stack[xop->xo_depth].xs_flags |= flags; rc = 0; break; } if (rc < 0) xo_failure(xop, "close %d failed: %d", xsp->xs_state, rc); } return 0; } /* * This function is responsible for clearing out whatever is needed * to get to the desired state, if possible. */ static int xo_do_close (xo_handle_t *xop, const char *name, xo_state_t new_state) { xo_stack_t *xsp, *limit = NULL; ssize_t rc; xo_state_t need_state = new_state; if (new_state == XSS_CLOSE_CONTAINER) need_state = XSS_OPEN_CONTAINER; else if (new_state == XSS_CLOSE_LIST) need_state = XSS_OPEN_LIST; else if (new_state == XSS_CLOSE_INSTANCE) need_state = XSS_OPEN_INSTANCE; else if (new_state == XSS_CLOSE_LEAF_LIST) need_state = XSS_OPEN_LEAF_LIST; else if (new_state == XSS_MARKER) need_state = XSS_MARKER; else return 0; /* Unknown or useless new states are ignored */ for (xsp = &xop->xo_stack[xop->xo_depth]; xsp > xop->xo_stack; xsp--) { /* * Marker's normally stop us from going any further, unless * we are popping a marker (new_state == XSS_MARKER). */ if (xsp->xs_state == XSS_MARKER && need_state != XSS_MARKER) { if (name) { xo_failure(xop, "close (xo_%s) fails at marker '%s'; " "not found '%s'", xo_state_name(new_state), xsp->xs_name, name); return 0; } else { limit = xsp; xo_failure(xop, "close stops at marker '%s'", xsp->xs_name); } break; } if (xsp->xs_state != need_state) continue; if (name && xsp->xs_name && strcmp(name, xsp->xs_name) != 0) continue; limit = xsp; break; } if (limit == NULL) { xo_failure(xop, "xo_%s can't find match for '%s'", xo_state_name(new_state), name); return 0; } rc = xo_do_close_all(xop, limit); return rc; } /* * We are in a given state and need to transition to the new state. */ static ssize_t xo_transition (xo_handle_t *xop, xo_xsf_flags_t flags, const char *name, xo_state_t new_state) { xo_stack_t *xsp; ssize_t rc = 0; int old_state, on_marker; xop = xo_default(xop); xsp = &xop->xo_stack[xop->xo_depth]; old_state = xsp->xs_state; on_marker = (old_state == XSS_MARKER); /* If there's a marker on top of the stack, we need to find a real state */ while (old_state == XSS_MARKER) { if (xsp == xop->xo_stack) break; xsp -= 1; old_state = xsp->xs_state; } /* * At this point, the list of possible states are: * XSS_INIT, XSS_OPEN_CONTAINER, XSS_OPEN_LIST, * XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST, XSS_DISCARDING */ switch (XSS_TRANSITION(old_state, new_state)) { open_container: case XSS_TRANSITION(XSS_INIT, XSS_OPEN_CONTAINER): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_CONTAINER): case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_CONTAINER): rc = xo_do_open_container(xop, flags, name); break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_CONTAINER): if (on_marker) goto marker_prevents_close; rc = xo_do_close_list(xop, NULL); if (rc >= 0) goto open_container; break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_CONTAINER): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); if (rc >= 0) goto open_container; break; /*close_container:*/ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_CONTAINER): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, name, new_state); break; case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_CONTAINER): /* This is an exception for "xo --close" */ rc = xo_do_close_container(xop, name); break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_CONTAINER): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_CONTAINER): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, name, new_state); break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_CONTAINER): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); if (rc >= 0) rc = xo_do_close(xop, name, new_state); break; open_list: case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LIST): case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LIST): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LIST): rc = xo_do_open_list(xop, flags, name); break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close_list(xop, NULL); if (rc >= 0) goto open_list; break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); if (rc >= 0) goto open_list; break; /*close_list:*/ case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, name, new_state); break; case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LIST): case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LIST): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LIST): case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LIST): rc = xo_do_close(xop, name, new_state); break; open_instance: case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_INSTANCE): rc = xo_do_open_instance(xop, flags, name); break; case XSS_TRANSITION(XSS_INIT, XSS_OPEN_INSTANCE): case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_INSTANCE): rc = xo_do_open_list(xop, flags, name); if (rc >= 0) goto open_instance; break; case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_INSTANCE): if (on_marker) { rc = xo_do_open_list(xop, flags, name); } else { rc = xo_do_close_instance(xop, NULL); } if (rc >= 0) goto open_instance; break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_INSTANCE): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); if (rc >= 0) goto open_instance; break; /*close_instance:*/ case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_INSTANCE): if (on_marker) goto marker_prevents_close; rc = xo_do_close_instance(xop, name); break; case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_INSTANCE): /* This one makes no sense; ignore it */ xo_failure(xop, "xo_close_instance ignored when called from " "initial state ('%s')", name ?: "(unknown)"); break; case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_INSTANCE): case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_INSTANCE): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, name, new_state); break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_INSTANCE): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); if (rc >= 0) rc = xo_do_close(xop, name, new_state); break; open_leaf_list: case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_OPEN_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_OPEN_LEAF_LIST): case XSS_TRANSITION(XSS_INIT, XSS_OPEN_LEAF_LIST): rc = xo_do_open_leaf_list(xop, flags, name); break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_OPEN_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_OPEN_LEAF_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close_list(xop, NULL); if (rc >= 0) goto open_leaf_list; break; /*close_leaf_list:*/ case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_CLOSE_LEAF_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, name); break; case XSS_TRANSITION(XSS_INIT, XSS_CLOSE_LEAF_LIST): /* Makes no sense; ignore */ xo_failure(xop, "xo_close_leaf_list ignored when called from " "initial state ('%s')", name ?: "(unknown)"); break; case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_CLOSE_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_LIST, XSS_CLOSE_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_CLOSE_LEAF_LIST): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, name, new_state); break; /*emit:*/ case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT): break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT): if (on_marker) goto marker_prevents_close; rc = xo_do_close(xop, NULL, XSS_CLOSE_LIST); break; case XSS_TRANSITION(XSS_INIT, XSS_EMIT): break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT): if (on_marker) goto marker_prevents_close; rc = xo_do_close_leaf_list(xop, NULL); break; /*emit_leaf_list:*/ case XSS_TRANSITION(XSS_INIT, XSS_EMIT_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_CONTAINER, XSS_EMIT_LEAF_LIST): case XSS_TRANSITION(XSS_OPEN_INSTANCE, XSS_EMIT_LEAF_LIST): rc = xo_do_open_leaf_list(xop, flags, name); break; case XSS_TRANSITION(XSS_OPEN_LEAF_LIST, XSS_EMIT_LEAF_LIST): break; case XSS_TRANSITION(XSS_OPEN_LIST, XSS_EMIT_LEAF_LIST): /* * We need to be backward compatible with the pre-xo_open_leaf_list * API, where both lists and leaf-lists were opened as lists. So * if we find an open list that hasn't had anything written to it, * we'll accept it. */ break; default: xo_failure(xop, "unknown transition: (%u -> %u)", xsp->xs_state, new_state); } /* Handle the flush flag */ if (rc >= 0 && XOF_ISSET(xop, XOF_FLUSH)) if (xo_flush_h(xop)) rc = -1; return rc; marker_prevents_close: xo_failure(xop, "marker '%s' prevents transition from %s to %s", xop->xo_stack[xop->xo_depth].xs_name, xo_state_name(old_state), xo_state_name(new_state)); return -1; } xo_ssize_t xo_open_marker_h (xo_handle_t *xop, const char *name) { xop = xo_default(xop); xo_depth_change(xop, name, 1, 0, XSS_MARKER, xop->xo_stack[xop->xo_depth].xs_flags & XSF_MARKER_FLAGS); return 0; } xo_ssize_t xo_open_marker (const char *name) { return xo_open_marker_h(NULL, name); } xo_ssize_t xo_close_marker_h (xo_handle_t *xop, const char *name) { xop = xo_default(xop); return xo_do_close(xop, name, XSS_MARKER); } xo_ssize_t xo_close_marker (const char *name) { return xo_close_marker_h(NULL, name); } /* * Record custom output functions into the xo handle, allowing * integration with a variety of output frameworks. */ void xo_set_writer (xo_handle_t *xop, void *opaque, xo_write_func_t write_func, xo_close_func_t close_func, xo_flush_func_t flush_func) { xop = xo_default(xop); xop->xo_opaque = opaque; xop->xo_write = write_func; xop->xo_close = close_func; xop->xo_flush = flush_func; } void xo_set_allocator (xo_realloc_func_t realloc_func, xo_free_func_t free_func) { xo_realloc = realloc_func; xo_free = free_func; } xo_ssize_t xo_flush_h (xo_handle_t *xop) { ssize_t rc; xop = xo_default(xop); switch (xo_style(xop)) { case XO_STYLE_ENCODER: xo_encoder_handle(xop, XO_OP_FLUSH, NULL, NULL, 0); } rc = xo_write(xop); if (rc >= 0 && xop->xo_flush) if (xop->xo_flush(xop->xo_opaque) < 0) return -1; return rc; } xo_ssize_t xo_flush (void) { return xo_flush_h(NULL); } xo_ssize_t xo_finish_h (xo_handle_t *xop) { const char *cp = ""; xop = xo_default(xop); if (!XOF_ISSET(xop, XOF_NO_CLOSE)) xo_do_close_all(xop, xop->xo_stack); switch (xo_style(xop)) { case XO_STYLE_JSON: if (!XOF_ISSET(xop, XOF_NO_TOP)) { if (XOIF_ISSET(xop, XOIF_TOP_EMITTED)) XOIF_CLEAR(xop, XOIF_TOP_EMITTED); /* Turn off before output */ else cp = "{ "; xo_printf(xop, "%*s%s}\n",xo_indent(xop), "", cp); } break; case XO_STYLE_ENCODER: xo_encoder_handle(xop, XO_OP_FINISH, NULL, NULL, 0); break; } return xo_flush_h(xop); } xo_ssize_t xo_finish (void) { return xo_finish_h(NULL); } /* * xo_finish_atexit is suitable for atexit() calls, to force clear up * and finalizing output. */ void xo_finish_atexit (void) { (void) xo_finish_h(NULL); } /* * Generate an error message, such as would be displayed on stderr */ void xo_error_hv (xo_handle_t *xop, const char *fmt, va_list vap) { xop = xo_default(xop); /* * If the format string doesn't end with a newline, we pop * one on ourselves. */ ssize_t len = strlen(fmt); if (len > 0 && fmt[len - 1] != '\n') { char *newfmt = alloca(len + 2); memcpy(newfmt, fmt, len); newfmt[len] = '\n'; newfmt[len] = '\0'; fmt = newfmt; } switch (xo_style(xop)) { case XO_STYLE_TEXT: vfprintf(stderr, fmt, vap); break; case XO_STYLE_HTML: va_copy(xop->xo_vap, vap); xo_buf_append_div(xop, "error", 0, NULL, 0, NULL, 0, fmt, strlen(fmt), NULL, 0); if (XOIF_ISSET(xop, XOIF_DIV_OPEN)) xo_line_close(xop); xo_write(xop); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); break; case XO_STYLE_XML: case XO_STYLE_JSON: va_copy(xop->xo_vap, vap); xo_open_container_h(xop, "error"); xo_format_value(xop, "message", 7, NULL, 0, fmt, strlen(fmt), NULL, 0, 0); xo_close_container_h(xop, "error"); va_end(xop->xo_vap); bzero(&xop->xo_vap, sizeof(xop->xo_vap)); break; case XO_STYLE_SDPARAMS: case XO_STYLE_ENCODER: break; } } void xo_error_h (xo_handle_t *xop, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_error_hv(xop, fmt, vap); va_end(vap); } /* * Generate an error message, such as would be displayed on stderr */ void xo_error (const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_error_hv(NULL, fmt, vap); va_end(vap); } /* * Parse any libxo-specific options from the command line, removing them * so the main() argument parsing won't see them. We return the new value * for argc or -1 for error. If an error occurred, the program should * exit. A suitable error message has already been displayed. */ int xo_parse_args (int argc, char **argv) { static char libxo_opt[] = "--libxo"; char *cp; int i, save; /* Save our program name for xo_err and friends */ xo_program = argv[0]; cp = strrchr(xo_program, '/'); if (cp) xo_program = cp + 1; xo_handle_t *xop = xo_default(NULL); for (save = i = 1; i < argc; i++) { if (argv[i] == NULL || strncmp(argv[i], libxo_opt, sizeof(libxo_opt) - 1) != 0) { if (save != i) argv[save] = argv[i]; save += 1; continue; } cp = argv[i] + sizeof(libxo_opt) - 1; if (*cp == '\0') { cp = argv[++i]; if (cp == NULL) { xo_warnx("missing libxo option"); return -1; } if (xo_set_options(xop, cp) < 0) return -1; } else if (*cp == ':') { if (xo_set_options(xop, cp) < 0) return -1; } else if (*cp == '=') { if (xo_set_options(xop, ++cp) < 0) return -1; } else if (*cp == '-') { cp += 1; if (strcmp(cp, "check") == 0) { exit(XO_HAS_LIBXO); } else { xo_warnx("unknown libxo option: '%s'", argv[i]); return -1; } } else { xo_warnx("unknown libxo option: '%s'", argv[i]); return -1; } } /* * We only want to do color output on terminals, but we only want * to do this if the user has asked for color. */ if (XOF_ISSET(xop, XOF_COLOR_ALLOWED) && isatty(1)) XOF_SET(xop, XOF_COLOR); argv[save] = NULL; return save; } /* * Debugging function that dumps the current stack of open libxo constructs, * suitable for calling from the debugger. */ void xo_dump_stack (xo_handle_t *xop) { int i; xo_stack_t *xsp; xop = xo_default(xop); fprintf(stderr, "Stack dump:\n"); xsp = xop->xo_stack; for (i = 1, xsp++; i <= xop->xo_depth; i++, xsp++) { fprintf(stderr, " [%d] %s '%s' [%x]\n", i, xo_state_name(xsp->xs_state), xsp->xs_name ?: "--", xsp->xs_flags); } } /* * Record the program name used for error messages */ void xo_set_program (const char *name) { xo_program = name; } void xo_set_version_h (xo_handle_t *xop, const char *version) { xop = xo_default(xop); if (version == NULL || strchr(version, '"') != NULL) return; if (!xo_style_is_encoding(xop)) return; switch (xo_style(xop)) { case XO_STYLE_XML: /* For XML, we record this as an attribute for the first tag */ xo_attr_h(xop, "version", "%s", version); break; case XO_STYLE_JSON: /* * For JSON, we record the version string in our handle, and emit * it in xo_emit_top. */ xop->xo_version = xo_strndup(version, -1); break; case XO_STYLE_ENCODER: xo_encoder_handle(xop, XO_OP_VERSION, NULL, version, 0); break; } } /* * Set the version number for the API content being carried through * the xo handle. */ void xo_set_version (const char *version) { xo_set_version_h(NULL, version); } /* * Generate a warning. Normally, this is a text message written to * standard error. If the XOF_WARN_XML flag is set, then we generate * XMLified content on standard output. */ void xo_emit_warn_hcv (xo_handle_t *xop, int as_warning, int code, const char *fmt, va_list vap) { xop = xo_default(xop); if (fmt == NULL) return; xo_open_marker_h(xop, "xo_emit_warn_hcv"); xo_open_container_h(xop, as_warning ? "__warning" : "__error"); if (xo_program) xo_emit("{wc:program}", xo_program); if (xo_style(xop) == XO_STYLE_XML || xo_style(xop) == XO_STYLE_JSON) { va_list ap; xo_handle_t temp; bzero(&temp, sizeof(temp)); temp.xo_style = XO_STYLE_TEXT; xo_buf_init(&temp.xo_data); xo_depth_check(&temp, XO_DEPTH); va_copy(ap, vap); (void) xo_emit_hv(&temp, fmt, ap); va_end(ap); xo_buffer_t *src = &temp.xo_data; xo_format_value(xop, "message", 7, src->xb_bufp, src->xb_curp - src->xb_bufp, NULL, 0, NULL, 0, 0); xo_free(temp.xo_stack); xo_buf_cleanup(src); } (void) xo_emit_hv(xop, fmt, vap); ssize_t len = strlen(fmt); if (len > 0 && fmt[len - 1] != '\n') { if (code > 0) { const char *msg = strerror(code); if (msg) xo_emit_h(xop, ": {G:strerror}{g:error/%s}", msg); } xo_emit("\n"); } xo_close_marker_h(xop, "xo_emit_warn_hcv"); xo_flush_h(xop); } void xo_emit_warn_hc (xo_handle_t *xop, int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_emit_warn_hcv(xop, 1, code, fmt, vap); va_end(vap); } void xo_emit_warn_c (int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_emit_warn_hcv(NULL, 1, code, fmt, vap); va_end(vap); } void xo_emit_warn (const char *fmt, ...) { int code = errno; va_list vap; va_start(vap, fmt); xo_emit_warn_hcv(NULL, 1, code, fmt, vap); va_end(vap); } void xo_emit_warnx (const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_emit_warn_hcv(NULL, 1, -1, fmt, vap); va_end(vap); } void xo_emit_err_v (int eval, int code, const char *fmt, va_list vap) { xo_emit_warn_hcv(NULL, 0, code, fmt, vap); xo_finish(); exit(eval); } void xo_emit_err (int eval, const char *fmt, ...) { int code = errno; va_list vap; va_start(vap, fmt); xo_emit_err_v(0, code, fmt, vap); va_end(vap); exit(eval); } void xo_emit_errx (int eval, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_emit_err_v(0, -1, fmt, vap); va_end(vap); xo_finish(); exit(eval); } void xo_emit_errc (int eval, int code, const char *fmt, ...) { va_list vap; va_start(vap, fmt); xo_emit_warn_hcv(NULL, 0, code, fmt, vap); va_end(vap); xo_finish(); exit(eval); } /* * Get the opaque private pointer for an xo handle */ void * xo_get_private (xo_handle_t *xop) { xop = xo_default(xop); return xop->xo_private; } /* * Set the opaque private pointer for an xo handle. */ void xo_set_private (xo_handle_t *xop, void *opaque) { xop = xo_default(xop); xop->xo_private = opaque; } /* * Get the encoder function */ xo_encoder_func_t xo_get_encoder (xo_handle_t *xop) { xop = xo_default(xop); return xop->xo_encoder; } /* * Record an encoder callback function in an xo handle. */ void xo_set_encoder (xo_handle_t *xop, xo_encoder_func_t encoder) { xop = xo_default(xop); xop->xo_style = XO_STYLE_ENCODER; xop->xo_encoder = encoder; } Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_attr.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_attr.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_attr.3 (revision 322022) @@ -1,60 +1,70 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd July, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_attr , xo_attr_h , xo_attr_hv .Nd Add attribute name/value pairs to formatted output .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_attr "const char *name" "const char *fmt" "..." .Ft int .Fn xo_attr_h "xo_handle_t *handle" "const char *name, const char *fmt" "..." .Ft int .Fn xo_attr_hv "xo_handle_t *handle" "const char *name" "const char *fmt" "va_list vap" .Sh DESCRIPTION The .Fn xo_attr function emits attributes for the XML output style. The attribute value is recorded in the .Fa handle and is attached to the next field that is emitted via a .Xr xo_emit 3 call. .Pp The .Fa name parameter give the name of the attribute to be encoded. The .Fa fmt parameter gives a printf-style format string used to format the value of the attribute using any remaining arguments, or the .Fa vap parameter as passed to .Fn xo_attr_hv . .Bd -literal -offset indent EXAMPLE: xo_attr("seconds", "%ld", (unsigned long) login_time); struct tm *tmp = localtime(login_time); strftime(buf, sizeof(buf), "%R", tmp); xo_emit("Logged in at {:login-time}\\n", buf); XML: 00:14 .Ed .Pp Since attributes are only emitted in XML, their use should be limited to meta-data and additional or redundant representations of data already emitted in other form. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_create.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_create.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_create.3 (revision 322022) @@ -1,67 +1,77 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_create , xo_create_to_file , xo_destroy .Nd create and destroy libxo output handles .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft xo_handle_t * .Fn xo_create "unsigned style" "unsigned flags" .Ft xo_handle_t * .Fn xo_create_to_file "FILE *fp" "unsigned style" "unsigned flags" .Ft void .Fn xo_destroy "xo_handle_t *handle" .Sh DESCRIPTION A .Nm libxo handle can be allocated using the .Fn xo_create function. .Bd -literal -offset indent Example: xo_handle_t *xop = xo_create(XO_STYLE_JSON, XOF_WARN); .... xo_emit_h(xop, "testing\n"); .Ed .Pp By default, .Nm libxo writes output to standard output. A convenience function is provided for situations when output should be written to a different file. .Pp Use the .Dv XOF_CLOSE_FP flag to trigger a call to .Xr fclose 3 for the .Dv FILE pointer when the handle is destroyed. .Pp The .Fn xo_destroy function releases a handle and any resources it is using. Calling .Fn xo_destroy with a .Dv NULL handle will release any resources associated with the default handle. .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_set_options 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_emit.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_emit.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_emit.3 (revision 322022) @@ -1,104 +1,114 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_emit , xo_emit_h , xo_emit_hv .Nd emit formatted output based on format string and arguments .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_emit "const char *fmt" "..." .Ft int .Fn xo_emit_h "xo_handle_t *xop" "const char *fmt" "..." .Ft int .Fn xo_emit_hv "xo_handle_t *xop" "const char *fmt" "va_list vap" .Sh DESCRIPTION The .Fn xo_emit function emits formatted output using the description in a format string along with a set of zero or more arguments, in a style similar to .Xr printf 3 but using a more complex format description string, as described in .Xr xo_format 5 . .Pp .Fn xo_emit uses the default output handle, as described in .Xr libxo 3 , where .Fn xo_emit_h uses an explicit handle. .Fn xo_emit_hv accepts a .Fa va_list for additional flexibility. .Sh EXAMPLES In this example, a set of four values is emitted using the following source code: .Bd -literal -offset indent xo_emit(" {:lines/%7ju} {:words/%7ju} " "{:characters/%7ju} {d:filename/%s}\n", linect, wordct, charct, file); .Ed Output can then be generated in various style, using the "--libxo" option: .Bd -literal -offset indent % wc /etc/motd 25 165 1140 /etc/motd % wc --libxo xml,pretty,warn /etc/motd 25 165 1140 /etc/motd % wc --libxo json,pretty,warn /etc/motd { "wc": { "file": [ { "lines": 25, "words": 165, "characters": 1140, "filename": "/etc/motd" } ] } } % wc --libxo html,pretty,warn /etc/motd
25
165
1140
/etc/motd
.Ed .Sh RETURN CODE .Nm returns a negative value on error. If the .Nm XOF_COLUMNS flag has been turned on for the specific handle using .Xr xo_set_flags 3 , then the number of display columns consumed by the output will be returned. .Sh SEE ALSO .Xr xo_open_container 3 , .Xr xo_open_list 3 , .Xr xo_format 5 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_err.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_err.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_err.3 (revision 322022) @@ -1,72 +1,82 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_emit_err , xo_emit_errc , xo_emit_errx .Nm xo_emit_warn , xo_emit_warnx , xo_emit_warn_c , xo_emit_warn_hc .Nd emit errors and warnings in multiple output styles .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_emit_warn "const char *fmt" "..." .Ft void .Fn xo_emit_warnx "const char *fmt" "..." .Ft void .Fn xo_emit_warn_c "int code" "const char *fmt" "..." .Ft void .Fn xo_emit_warn_hc "xo_handle_t *xop" "int code, const char *fmt" "..." .Ft void .Fn xo_emit_err "int eval" "const char *fmt" "..." .Ft void .Fn xo_emit_errc "int eval" "int code" "const char *fmt" "..." .Ft void .Fn xo_emit_errx "int eval" "const char *fmt" "..." .Sh DESCRIPTION Many programs make use of the standard library functions .Xr err 3 and .Xr warn 3 to generate errors and warnings for the user. .Nm libxo wants to pass that information via the current output style, and provides compatible functions to allow this. .Pp The .Fa fmt argument is one compatible with .Xr xo_emit 3 which allows these functions make structured data. To generate unstructured data, use the .Xr xo_err 3 functions. .Pp These functions display the program name, a colon, a formatted message based on the arguments, and then optionally a colon and an error message associated with either .Fa errno or the .Fa code parameter. .Bd -literal -offset indent EXAMPLE: if (open(filename, O_RDONLY) < 0) xo_err(1, "cannot open file '%s'", filename); .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_format 5 , .Xr xo_err 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_f.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_f.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_emit_f.3 (revision 322022) @@ -1,111 +1,121 @@ .\" # .\" # Copyright (c) 2016, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, April 2016 .\" .Dd April 15, 2016 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_emit_f , xo_emit_hf , xo_emit_hvf .Nd emit formatted output based on format string and arguments .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_emit_f "xo_emit_flags_t flags" "const char *fmt" "..." .Ft int .Fn xo_emit_hf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "..." .Ft int .Fn xo_emit_hvf "xo_handle_t *xop" "xo_emit_flags_t flags" "const char *fmt" "va_list vap" .Ft void .Fn xo_retain_clear_all "void" .Ft void .Fn xo_retain_clear "const char *fmt" .Sh DESCRIPTION These functions allow callers to pass a set of flags to .Nm emitting functions. These processing of arguments, except for .Fa flags , is identical to the base functions. See .Xr xo_emit 3 for additional information. .Pp The only currently defined flag is .Dv XOEF_RETAIN . .Nm can retain the parsed internal information related to the given format string, allowing subsequent .Xr xo_emit 3 calls, the retained information is used, avoiding repetitive parsing of the format string. To retain parsed format information, use the .Dv XOEF_RETAIN flag to the .Fn xo_emit_f function. .Pp The format string must be immutable across multiple calls to .Xn xo_emit_f , since the library retains the string. Typically this is done by using static constant strings, such as string literals. If the string is not immutable, the .Dv XOEF_RETAIN flag must not be used. .Pp The functions .Fn xo_retain_clear and .Fn xo_retain_clear_all release internal information on either a single format string or all format strings, respectively. Neither is required, but the library will retain this information until it is cleared or the process exits. .Pp The retained information is kept as thread-specific data. .Pp Use .Fn xo_retain_clear and .Fn xo_retain_clear_all to clear the retained information, clearing the retained information for either a specific format string or all format strings, respectively. These functions are only needed when the calling application wants to clear this information; they are not generally needed. .Sh EXAMPLES .Pp .Bd -literal -offset indent for (i = 0; i < 1000; i++) { xo_open_instance("item"); xo_emit_f(XOEF_RETAIN, "{:name} {:count/%d}\n", name[i], count[i]); } .Ed .Pp In this example, the caller desires to clear the retained information. .Bd -literal -offset indent const char *fmt = "{:name} {:count/%d}\n"; for (i = 0; i < 1000; i++) { xo_open_instance("item"); xo_emit_f(XOEF_RETAIN, fmt, name[i], count[i]); } xo_retain_clear(fmt); .Ed .Sh RETURN CODE The return values for these functions is identical to those of their traditional counterparts. See .Xr xo_emit 3 for details. .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_open_container 3 , .Xr xo_open_list 3 , .Xr xo_format 5 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_err.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_err.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_err.3 (revision 322022) @@ -1,74 +1,84 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_err , xo_errc , xo_errx .Nm xo_warn , xo_warnx , xo_warn_c , xo_warn_hc .Nd emit errors and warnings in multiple output styles .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_warn "const char *fmt" "..." .Ft void .Fn xo_warnx "const char *fmt" "..." .Ft void .Fn xo_warn_c "int code" "const char *fmt" "..." .Ft void .Fn xo_warn_hc "xo_handle_t *xop" "int code, const char *fmt" "..." .Ft void .Fn xo_err "int eval" "const char *fmt" "..." .Ft void .Fn xo_errc "int eval" "int code" "const char *fmt" "..." .Ft void .Fn xo_errx "int eval" "const char *fmt" "..." .Sh DESCRIPTION Many programs make use of the standard library functions .Xr err 3 and .Xr warn 3 to generate errors and warnings for the user. .Nm libxo wants to pass that information via the current output style, and provides compatible functions to allow this. .Pp The .Fa fmt argument is one compatible with .Xr printf 3 rather than .Xr xo_emit 3 to aid in simple conversion. This means these functions make unstructured data. To generate structured data, use the .Xr xo_emit_err 3 functions. .Pp These functions display the program name, a colon, a formatted message based on the arguments, and then optionally a colon and an error message associated with either .Fa errno or the .Fa code parameter. .Bd -literal -offset indent EXAMPLE: if (open(filename, O_RDONLY) < 0) xo_err(1, "cannot open file '%s'", filename); .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_emit_err 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_error.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_error.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_error.3 (revision 322022) @@ -1,41 +1,51 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_error .Nd generate simple error messages in multiple output styles .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_error "const char *fmt" "..." .Sh DESCRIPTION Use the .Fn xo_error function to generate error messages to standard error. The .Fa fmt argument is a string containing printf-style formatting instructions that describe the remaining arguments. .Pp When converting an application to .Nm libxo , one can replace .Em "fprintf(stderr,...)" calls with .Fn xo_error calls. .Sh SEE ALSO .Xr printf 3 , .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_finish.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_finish.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_finish.3 (revision 322022) @@ -1,39 +1,49 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_finish , xo_finish_h .Nd finish formatting output .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_finish "void" .Ft void .Fn xo_finish_h "xo_handle_t *xop" .Sh DESCRIPTION When the program is ready to exit or close a handle, a call to .Fn xo_finish is required. This flushes any buffered data, closes open .Nm libxo constructs, and completes any pending operations. .Pp Calling this function is .Em vital to the proper operation of libxo, especially for the non-TEXT output styles. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_flush.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_flush.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_flush.3 (revision 322022) @@ -1,35 +1,45 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_flush , xo_flush_h .Nd flush formatted output from libxo handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_flush "void" .Ft void .Fn xo_flush_h "xo_handle_t *handle" .Sh DESCRIPTION .Nm libxo buffers data, both for performance and consistency, but also to allow some advanced features to work properly. At various times, the caller may wish to flush any data buffered within the library. The .Fn xo_flush function is used for this. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_format.5 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_format.5 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_format.5 (revision 322022) @@ -1,967 +1,977 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_format .Nd content of format descriptors for xo_emit .Sh DESCRIPTION .Pp .Nm libxo uses format strings to control the rendering of data into various output styles, including .Em text , .Em XML , .Em JSON , and .Em HTML . Each format string contains a set of zero or more .Dq "field descriptions" , which describe independent data fields. Each field description contains a set of .Dq modifiers , a .Dq "content string" , and zero, one, or two .Dq "format descriptors" . The modifiers tell .Nm libxo what the field is and how to treat it, while the format descriptors are formatting instructions using .Xr printf 3 Ns -style format strings, telling .Nm libxo how to format the field. The field description is placed inside a set of braces, with a colon .Ql ( \&: ) after the modifiers and a slash .Ql ( \&/ ) before each format descriptors. Text may be intermixed with field descriptions within the format string. .Pp The field description is given as follows: .Bd -literal -offset indent \(aq{\(aq [ role | modifier ]* [\(aq,\(aq long\-names ]* \(aq:\(aq [ content ] [ \(aq/\(aq field\-format [ \(aq/\(aq encoding\-format ]] \(aq}\(aq .Ed .Pp The role describes the function of the field, while the modifiers enable optional behaviors. The contents, field\-format, and encoding\-format are used in varying ways, based on the role. These are described in the following sections. .Pp Braces can be escaped by using double braces, similar to "%%" in .Xr printf 3 . The format string "{{braces}}" would emit "{braces}". .Pp In the following example, three field descriptors appear. The first is a padding field containing three spaces of padding, the second is a label ("In stock"), and the third is a value field ("in\-stock"). The in\-stock field has a "%u" format that will parse the next argument passed to the .Xr xo_emit 3 , function as an unsigned integer. .Bd -literal -offset indent xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n", 65); .Ed .Pp This single line of code can generate text ("In stock: 65\\n"), XML ("65"), JSON (\(aq"in\-stock": 65\(aq), or HTML (too lengthy to be listed here). .Pp While roles and modifiers typically use single character for brevity, there are alternative names for each which allow more verbose formatting strings. These names must be preceded by a comma, and may follow any single\-character values: .Bd -literal -offset indent xo_emit("{L,white,colon:In stock}{,key:in\-stock/%u}\\n", 65); .Ed .Ss "Field Roles" Field roles are optional, and indicate the role and formatting of the content. The roles are listed below; only one role is permitted: .Bl -column "M" "Name12341234" .It Sy "M" "Name " "Description" .It C "color " "Field is a color or effect" .It D "decoration " "Field is non\-text (e.g. colon, comma)" .It E "error " "Field is an error message" .It L "label " "Field is text that prefixes a value" .It N "note " "Field is text that follows a value" .It P "padding " "Field is spaces needed for vertical alignment" .It T "title " "Field is a title value for headings" .It U "units " "Field is the units for the previous value field" .It V "value " "Field is the name of field (the default)" .It W "warning " "Field is a warning message" .It \&[ "start\-anchor" "Begin a section of anchored variable\-width text" .It \&] "stop\-anchor " "End a section of anchored variable\-width text" .El .Bd -literal -offset indent EXAMPLE: xo_emit("{L:Free}{D::}{P: }{:free/%u} {U:Blocks}\\n", free_blocks); .Ed .Pp When a role is not provided, the "value" role is used as the default. .Pp Roles and modifiers can also use more verbose names, when preceded by a comma: .Bd -literal -offset indent EXAMPLE: xo_emit("{,label:Free}{,decoration::}{,padding: }" "{,value:free/%u} {,units:Blocks}\\n", free_blocks); .Ed .Ss "The Color Role ({C:})" Colors and effects control how text values are displayed; they are used for display styles (TEXT and HTML). .Bd -literal -offset indent xo_emit("{C:bold}{:value}{C:no\-bold}\\n", value); .Ed .Pp Colors and effects remain in effect until modified by other "C"\-role fields. .Bd -literal -offset indent xo_emit("{C:bold}{C:inverse}both{C:no\-bold}only inverse\\n"); .Ed .Pp If the content is empty, the "reset" action is performed. .Bd -literal -offset indent xo_emit("{C:both,underline}{:value}{C:}\\n", value); .Ed .Pp The content should be a comma\-separated list of zero or more colors or display effects. .Bd -literal -offset indent xo_emit("{C:bold,underline,inverse}All three{C:no\-bold,no\-inverse}\\n"); .Ed .Pp The color content can be either static, when placed directly within the field descriptor, or a printf\-style format descriptor can be used, if preceded by a slash ("/"): .Bd -literal -offset indent xo_emit("{C:/%s%s}{:value}{C:}", need_bold ? "bold" : "", need_underline ? "underline" : "", value); .Ed .Pp Color names are prefixed with either "fg\-" or "bg\-" to change the foreground and background colors, respectively. .Bd -literal -offset indent xo_emit("{C:/fg\-%s,bg\-%s}{Lwc:Cost}{:cost/%u}{C:reset}\\n", fg_color, bg_color, cost); .Ed .Pp The following table lists the supported effects: .Bl -column "no\-underline" .It Sy "Name " "Description" .It "bg\-xxxxx " "Change background color" .It "bold " "Start bold text effect" .It "fg\-xxxxx " "Change foreground color" .It "inverse " "Start inverse (aka reverse) text effect" .It "no\-bold " "Stop bold text effect" .It "no\-inverse " "Stop inverse (aka reverse) text effect" .It "no\-underline " "Stop underline text effect" .It "normal " "Reset effects (only)" .It "reset " "Reset colors and effects (restore defaults)" .It "underline " "Start underline text effect" .El .Pp The following color names are supported: .Bl -column "no\-underline" .It Sy "Name" .It black .It blue .It cyan .It default .It green .It magenta .It red .It white .It yellow .El .Ss "The Decoration Role ({D:})" Decorations are typically punctuation marks such as colons, semi\-colons, and commas used to decorate the text and make it simpler for human readers. By marking these distinctly, HTML usage scenarios can use CSS to direct their display parameters. .Bd -literal -offset indent xo_emit("{D:((}{:name}{D:))}\\n", name); .Ed .Ss "The Gettext Role ({G:})" .Nm libxo supports internationalization (i18n) through its use of .Xr gettext 3 . Use the "{G:}" role to request that the remaining part of the format string, following the "{G:}" field, be handled using .Fn gettext . Since .Fn gettext uses the string as the key into the message catalog, .Nm libxo uses a simplified version of the format string that removes unimportant field formatting and modifiers, stopping minor formatting changes from impacting the expensive translation process. A developer change such as changing "/%06d" to "/%08d" should not force hand inspection of all .po files. .Pp The simplified version can be generated for a single message using the "xopo \-s " command, or an entire .pot can be translated using the "xopo \-f \-o " command. .Bd -literal -offset indent xo_emit("{G:}Invalid token\\n"); .Ed .Pp The {G:} role allows a domain name to be set. .Fn gettext calls will continue to use that domain name until the current format string processing is complete, enabling a library function to emit strings using it\(aqs own catalog. The domain name can be either static as the content of the field, or a format can be used to get the domain name from the arguments. .Bd -literal -offset indent xo_emit("{G:libc}Service unavailable in restricted mode\\n"); .Ed .Ss "The Label Role ({L:})" Labels are text that appears before a value. .Bd -literal -offset indent xo_emit("{Lwc:Cost}{:cost/%u}\\n", cost); .Ed .Ss "The Note Role ({N:})" Notes are text that appears after a value. .Bd -literal -offset indent xo_emit("{:cost/%u} {N:per year}\\n", cost); .Ed .Ss "The Padding Role ({P:})" Padding represents whitespace used before and between fields. The padding content can be either static, when placed directly within the field descriptor, or a printf\-style format descriptor can be used, if preceded by a slash ("/"): .Bd -literal -offset indent xo_emit("{P: }{Lwc:Cost}{:cost/%u}\\n", cost); xo_emit("{P:/30s}{Lwc:Cost}{:cost/%u}\\n", "", cost); .Ed .Ss "The Title Role ({T:})" Titles are heading or column headers that are meant to be displayed to the user. The title can be either static, when placed directly within the field descriptor, or a printf\-style format descriptor can be used, if preceded by a slash ("/"): .Bd -literal -offset indent xo_emit("{T:Interface Statistics}\\n"); xo_emit("{T:/%20.20s}{T:/%6.6s}\\n", "Item Name", "Cost"); .Ed .Ss "The Units Role ({U:})" Units are the dimension by which values are measured, such as degrees, miles, bytes, and decibels. The units field carries this information for the previous value field. .Bd -literal -offset indent xo_emit("{Lwc:Distance}{:distance/%u}{Uw:miles}\\n", miles); .Ed .Pp Note that the sense of the \(aqw\(aq modifier is reversed for units; a blank is added before the contents, rather than after it. .Pp When the .Dv XOF_UNITS flag is set, units are rendered in XML as the .Dq units attribute: .Bd -literal -offset indent 50 .Ed .Pp Units can also be rendered in HTML as the "data\-units" attribute: .Bd -literal -offset indent
50
.Ed .Ss "The Value Role ({V:} and {:})" The value role is used to represent the a data value that is interesting for the non\-display output styles (XML and JSON). Value is the default role; if no other role designation is given, the field is a value. The field name must appear within the field descriptor, followed by one or two format descriptors. The first format descriptor is used for display styles (TEXT and HTML), while the second one is used for encoding styles (XML and JSON). If no second format is given, the encoding format defaults to the first format, with any minimum width removed. If no first format is given, both format descriptors default to "%s". .Bd -literal -offset indent xo_emit("{:length/%02u}x{:width/%02u}x{:height/%02u}\\n", length, width, height); xo_emit("{:author} wrote \"{:poem}\" in {:year/%4d}\\n, author, poem, year); .Ed .Ss "The Anchor Roles ({[:} and {]:})" The anchor roles allow a set of strings by be padded as a group, but still be visible to .Xr xo_emit 3 as distinct fields. Either the start or stop anchor can give a field width and it can be either directly in the descriptor or passed as an argument. Any fields between the start and stop anchor are padded to meet the minimum width given. .Pp To give a width directly, encode it as the content of the anchor tag: .Bd -literal -offset indent xo_emit("({[:10}{:min/%d}/{:max/%d}{]:})\\n", min, max); .Ed .Pp To pass a width as an argument, use "%d" as the format, which must appear after the "/". Note that only "%d" is supported for widths. Using any other value could ruin your day. .Bd -literal -offset indent xo_emit("({[:/%d}{:min/%d}/{:max/%d}{]:})\\n", width, min, max); .Ed .Pp If the width is negative, padding will be added on the right, suitable for left justification. Otherwise the padding will be added to the left of the fields between the start and stop anchors, suitable for right justification. If the width is zero, nothing happens. If the number of columns of output between the start and stop anchors is less than the absolute value of the given width, nothing happens. .Pp Widths over 8k are considered probable errors and not supported. If .Dv XOF_WARN is set, a warning will be generated. .Ss "Field Modifiers" Field modifiers are flags which modify the way content emitted for particular output styles: .Bl -column M "Name123456789" .It Sy M "Name " "Description" .It a "argument " "The content appears as a ""const char *"" argument" .It c "colon " "A colon ("":"") is appended after the label" .It d "display " "Only emit field for display styles (text/HTML)" .It e "encoding " "Only emit for encoding styles (XML/JSON)" .It h "humanize (hn) " "Format large numbers in human\-readable style" .It " " "hn\-space " "Humanize: Place space between numeric and unit" .It " " "hn\-decimal " "Humanize: Add a decimal digit, if number < 10" .It " " "hn\-1000 " "Humanize: Use 1000 as divisor instead of 1024" .It k "key " "Field is a key, suitable for XPath predicates" .It l "leaf\-list " "Field is a leaf\-list, a list of leaf values" .It n "no\-quotes " "Do not quote the field when using JSON style" .It q "quotes " "Quote the field when using JSON style" .It t "trim " "Trim leading and trailing whitespace" .It w "white space " "A blank ("" "") is appended after the label" .El .Pp For example, the modifier string "Lwc" means the field has a label role (text that describes the next field) and should be followed by a colon (\(aqc\(aq) and a space (\(aqw\(aq). The modifier string "Vkq" means the field has a value role, that it is a key for the current instance, and that the value should be quoted when encoded for JSON. .Pp Roles and modifiers can also use more verbose names, when preceded by a comma. For example, the modifier string "Lwc" (or "L,white,colon") means the field has a label role (text that describes the next field) and should be followed by a colon (\(aqc\(aq) and a space (\(aqw\(aq). The modifier string "Vkq" (or ":key,quote") means the field has a value role (the default role), that it is a key for the current instance, and that the value should be quoted when encoded for JSON. .Ss "The Argument Modifier ({a:})" The argument modifier indicates that the content of the field descriptor will be placed as a UTF\-8 string (const char *) argument within the xo_emit parameters. .Bd -literal -offset indent EXAMPLE: xo_emit("{La:} {a:}\\n", "Label text", "label", "value"); TEXT: Label text value JSON: "label": "value" XML: .Ed .Pp The argument modifier allows field names for value fields to be passed on the stack, avoiding the need to build a field descriptor using .Xr snprintf 1 . For many field roles, the argument modifier is not needed, since those roles have specific mechanisms for arguments, such as "{C:fg\-%s}". .Ss "The Colon Modifier ({c:})" The colon modifier appends a single colon to the data value: .Bd -literal -offset indent EXAMPLE: xo_emit("{Lc:Name}{:name}\\n", "phil"); TEXT: Name:phil .Ed .Pp The colon modifier is only used for the TEXT and HTML output styles. It is commonly combined with the space modifier (\(aq{w:}\(aq). It is purely a convenience feature. .Ss "The Display Modifier ({d:})" The display modifier indicated the field should only be generated for the display output styles, TEXT and HTML. .Bd -literal -offset indent EXAMPLE: xo_emit("{Lcw:Name}{d:name} {:id/%d}\\n", "phil", 1); TEXT: Name: phil 1 XML: 1 .Ed .Pp The display modifier is the opposite of the encoding modifier, and they are often used to give to distinct views of the underlying data. .Ss "The Encoding Modifier ({e:})" The encoding modifier indicated the field should only be generated for the encoding output styles, such as JSON and XML. .Bd -literal -offset indent EXAMPLE: xo_emit("{Lcw:Name}{:name} {e:id/%d}\\n", "phil", 1); TEXT: Name: phil XML: phil1 .Ed .Pp The encoding modifier is the opposite of the display modifier, and they are often used to give to distinct views of the underlying data. .Ss "The Humanize Modifier ({h:})" The humanize modifier is used to render large numbers as in a human\-readable format. While numbers like "44470272" are completely readable to computers and savants, humans will generally find "44M" more meaningful. .Pp "hn" can be used as an alias for "humanize". .Pp The humanize modifier only affects display styles (TEXT and HMTL). The "no\-humanize" option will block the function of the humanize modifier. .Pp There are a number of modifiers that affect details of humanization. These are only available in as full names, not single characters. The "hn\-space" modifier places a space between the number and any multiplier symbol, such as "M" or "K" (ex: "44 K"). The "hn\-decimal" modifier will add a decimal point and a single tenths digit when the number is less than 10 (ex: "4.4K"). The "hn\-1000" modifier will use 1000 as divisor instead of 1024, following the JEDEC\-standard instead of the more natural binary powers\-of\-two tradition. .Bd -literal -offset indent EXAMPLE: xo_emit("{h:input/%u}, {h,hn\-space:output/%u}, " "{h,hn\-decimal:errors/%u}, {h,hn\-1000:capacity/%u}, " "{h,hn\-decimal:remaining/%u}\\n", input, output, errors, capacity, remaining); TEXT: 21, 57 K, 96M, 44M, 1.2G .Ed .Pp In the HTML style, the original numeric value is rendered in the "data\-number" attribute on the
element: .Bd -literal -offset indent
96M
.Ed .Ss "The Gettext Modifier ({g:})" The gettext modifier is used to translate individual fields using the gettext domain (typically set using the "{G:}" role) and current language settings. Once libxo renders the field value, it is passed to .Xr gettext 3 , where it is used as a key to find the native language translation. .Pp In the following example, the strings "State" and "full" are passed to .Fn gettext to find locale\-based translated strings. .Bd -literal -offset indent xo_emit("{Lgwc:State}{g:state}\\n", "full"); .Ed .Ss "The Key Modifier ({k:})" The key modifier is used to indicate that a particular field helps uniquely identify an instance of list data. .Bd -literal -offset indent EXAMPLE: xo_open_list("user"); for (i = 0; i < num_users; i++) { xo_open_instance("user"); xo_emit("User {k:name} has {:count} tickets\\n", user[i].u_name, user[i].u_tickets); xo_close_instance("user"); } xo_close_list("user"); .Ed .Pp Currently the key modifier is only used when generating XPath values for the HTML output style when .Dv XOF_XPATH is set, but other uses are likely in the near future. .Ss "The Leaf\-List Modifier ({l:})" The leaf\-list modifier is used to distinguish lists where each instance consists of only a single value. In XML, these are rendered as single elements, where JSON renders them as arrays. .Bd -literal -offset indent EXAMPLE: xo_open_list("user"); for (i = 0; i < num_users; i++) { xo_emit("Member {l:name}\\n", user[i].u_name); } xo_close_list("user"); XML: phil pallavi JSON: "user": [ "phil", "pallavi" ] .Ed .Ss "The No\-Quotes Modifier ({n:})" The no\-quotes modifier (and its twin, the \(aqquotes\(aq modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string values, but no quotes for numeric, boolean, and null data. .Xr xo_emit 3 applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller. .Bd -literal -offset indent EXAMPLE: const char *bool = is_true ? "true" : "false"; xo_emit("{n:fancy/%s}", bool); JSON: "fancy": true .Ed .Ss "The Plural Modifier ({p:})" The plural modifier selects the appropriate plural form of an expression based on the most recent number emitted and the current language settings. The contents of the field should be the singular and plural English values, separated by a comma: .Bd -literal -offset indent xo_emit("{:bytes} {Ngp:byte,bytes}\\n", bytes); .Ed .Pp The plural modifier is meant to work with the gettext modifier ({g:}) but can work independently. .Pp When used without the gettext modifier or when the message does not appear in the message catalog, the first token is chosen when the last numeric value is equal to 1; otherwise the second value is used, mimicking the simple pluralization rules of English. .Pp When used with the gettext modifier, the .Xr ngettext 3 function is called to handle the heavy lifting, using the message catalog to convert the singular and plural forms into the native language. .Ss "The Quotes Modifier ({q:})" The quotes modifier (and its twin, the \(aqno-quotes\(aq modifier) affect the quoting of values in the JSON output style. JSON uses quotes for string values, but no quotes for numeric, boolean, and null data. .Xr xo_emit 3 applies a simple heuristic to determine whether quotes are needed, but often this needs to be controlled by the caller. .Bd -literal -offset indent EXAMPLE: xo_emit("{q:time/%d}", 2014); JSON: "year": "2014" .Ed .Ss "The White Space Modifier ({w:})" The white space modifier appends a single space to the data value: .Bd -literal -offset indent EXAMPLE: xo_emit("{Lw:Name}{:name}\\n", "phil"); TEXT: Name phil .Ed .Pp The white space modifier is only used for the TEXT and HTML output styles. It is commonly combined with the colon modifier (\(aq{c:}\(aq). It is purely a convenience feature. .Pp Note that the sense of the \(aqw\(aq modifier is reversed for the units role ({Uw:}); a blank is added before the contents, rather than after it. .Ss "Field Formatting" The field format is similar to the format string for .Xr printf 3 . Its use varies based on the role of the field, but generally is used to format the field\(aqs contents. .Pp If the format string is not provided for a value field, it defaults to "%s". .Pp Note a field definition can contain zero or more printf\-style .Dq directives , which are sequences that start with a \(aq%\(aq and end with one of following characters: "diouxXDOUeEfFgGaAcCsSp". Each directive is matched by one of more arguments to the .Xr xo_emit 3 function. .Pp The format string has the form: .Bd -literal -offset indent \(aq%\(aq format\-modifier * format\-character .Ed .Pp The format\-modifier can be: .Bl -bullet .It a \(aq#\(aq character, indicating the output value should be prefixed with "0x", typically to indicate a base 16 (hex) value. .It a minus sign (\(aq\-\(aq), indicating the output value should be padded on the right instead of the left. .It a leading zero (\(aq0\(aq) indicating the output value should be padded on the left with zeroes instead of spaces (\(aq \(aq). .It one or more digits (\(aq0\(aq \- \(aq9\(aq) indicating the minimum width of the argument. If the width in columns of the output value is less than the minimum width, the value will be padded to reach the minimum. .It a period followed by one or more digits indicating the maximum number of bytes which will be examined for a string argument, or the maximum width for a non\-string argument. When handling ASCII strings this functions as the field width but for multi\-byte characters, a single character may be composed of multiple bytes. .Xr xo_emit 3 will never dereference memory beyond the given number of bytes. .It a second period followed by one or more digits indicating the maximum width for a string argument. This modifier cannot be given for non\-string arguments. .It one or more \(aqh\(aq characters, indicating shorter input data. .It one or more \(aql\(aq characters, indicating longer input data. .It a \(aqz\(aq character, indicating a \(aqsize_t\(aq argument. .It a \(aqt\(aq character, indicating a \(aqptrdiff_t\(aq argument. .It a \(aq \(aq character, indicating a space should be emitted before positive numbers. .It a \(aq+\(aq character, indicating sign should emitted before any number. .El .Pp Note that \(aqq\(aq, \(aqD\(aq, \(aqO\(aq, and \(aqU\(aq are considered deprecated and will be removed eventually. .Pp The format character is described in the following table: .Bl -column C "Argument Type12" .It Sy "C" "Argument Type " "Format" .It d "int " "base 10 (decimal)" .It i "int " "base 10 (decimal)" .It o "int " "base 8 (octal)" .It u "unsigned " "base 10 (decimal)" .It x "unsigned " "base 16 (hex)" .It X "unsigned long " "base 16 (hex)" .It D "long " "base 10 (decimal)" .It O "unsigned long " "base 8 (octal)" .It U "unsigned long " "base 10 (decimal)" .It e "double " "[\-]d.ddde+\-dd" .It E "double " "[\-]d.dddE+\-dd" .It f "double " "[\-]ddd.ddd" .It F "double " "[\-]ddd.ddd" .It g "double " "as \(aqe\(aq or \(aqf\(aq" .It G "double " "as \(aqE\(aq or \(aqF\(aq" .It a "double " "[\-]0xh.hhhp[+\-]d" .It A "double " "[\-]0Xh.hhhp[+\-]d" .It c "unsigned char " "a character" .It C "wint_t " "a character" .It s "char * " "a UTF\-8 string" .It S "wchar_t * " "a unicode/WCS string" .It p "void * " "\(aq%#lx\(aq" .El .Pp The \(aqh\(aq and \(aql\(aq modifiers affect the size and treatment of the argument: .Bl -column "Mod" "d, i " "o, u, x, X " .It Sy "Mod" "d, i " "o, u, x, X" .It "hh " "signed char " "unsigned char" .It "h " "short " "unsigned short" .It "l " "long " "unsigned long" .It "ll " "long long " "unsigned long long" .It "j " "intmax_t " "uintmax_t" .It "t " "ptrdiff_t " "ptrdiff_t" .It "z " "size_t " "size_t" .It "q " "quad_t " "u_quad_t" .El .Ss "UTF\-8 and Locale Strings" All strings for .Nm libxo must be UTF\-8. .Nm libxo will handle turning them into locale\-based strings for display to the user. .Pp For strings, the \(aqh\(aq and \(aql\(aq modifiers affect the interpretation of the bytes pointed to argument. The default \(aq%s\(aq string is a \(aqchar *\(aq pointer to a string encoded as UTF\-8. Since UTF\-8 is compatible with .Em ASCII data, a normal 7\-bit .Em ASCII string can be used. "%ls" expects a "wchar_t *" pointer to a wide\-character string, encoded as 32\-bit Unicode values. "%hs" expects a "char *" pointer to a multi\-byte string encoded with the current locale, as given by the .Ev LC_CTYPE , .Ev LANG , or .Ev LC_ALL environment variables. The first of this list of variables is used and if none of the variables are set, the locale defaults to .Em UTF\-8 . .Pp .Nm libxo will convert these arguments as needed to either UTF\-8 (for XML, JSON, and HTML styles) or locale\-based strings for display in text style. .Bd -literal -offset indent xo_emit("All strings are utf\-8 content {:tag/%ls}", L"except for wide strings"); .Ed .Pp "%S" is equivalent to "%ls". .Pp For example, a function is passed a locale\-base name, a hat size, and a time value. The hat size is formatted in a UTF\-8 (ASCII) string, and the time value is formatted into a wchar_t string. .Bd -literal -offset indent void print_order (const char *name, int size, struct tm *timep) { char buf[32]; const char *size_val = "unknown"; if (size > 0) snprintf(buf, sizeof(buf), "%d", size); size_val = buf; } wchar_t when[32]; wcsftime(when, sizeof(when), L"%d%b%y", timep); xo_emit("The hat for {:name/%hs} is {:size/%s}.\\n", name, size_val); xo_emit("It was ordered on {:order\-time/%ls}.\\n", when); } .Ed .Pp It is important to note that .Xr xo_emit 3 will perform the conversion required to make appropriate output. Text style output uses the current locale (as described above), while XML, JSON, and HTML use UTF\-8. .Pp UTF\-8 and locale\-encoded strings can use multiple bytes to encode one column of data. The traditional "precision" (aka "max\-width") value for "%s" printf formatting becomes overloaded since it specifies both the number of bytes that can be safely referenced and the maximum number of columns to emit. .Xr xo_emit 3 uses the precision as the former, and adds a third value for specifying the maximum number of columns. .Pp In this example, the name field is printed with a minimum of 3 columns and a maximum of 6. Up to ten bytes are in used in filling those columns. .Bd -literal -offset indent xo_emit("{:name/%3.10.6s}", name); .Ed .Ss "Characters Outside of Field Definitions" Characters in the format string that are not part of a field definition are copied to the output for the TEXT style, and are ignored for the JSON and XML styles. For HTML, these characters are placed in a
with class "text". .Bd -literal -offset indent EXAMPLE: xo_emit("The hat is {:size/%s}.\\n", size_val); TEXT: The hat is extra small. XML: extra small JSON: "size": "extra small" HTML:
The hat is
extra small
.
.Ed .Ss "\(aq%n\(aq is Not Supported" .Nm libxo does not support the \(aq%n\(aq directive. It is a bad idea and we just do not do it. .Ss "The Encoding Format (eformat)" The "eformat" string is the format string used when encoding the field for JSON and XML. If not provided, it defaults to the primary format with any minimum width removed. If the primary is not given, both default to "%s". .Sh EXAMPLE In this example, the value for the number of items in stock is emitted: .Bd -literal -offset indent xo_emit("{P: }{Lwc:In stock}{:in\-stock/%u}\\n", instock); .Ed .Pp This call will generate the following output: .Bd -literal -offset indent TEXT: In stock: 144 XML: 144 JSON: "in\-stock": 144, HTML:
In stock
:
144
.Ed .Pp Clearly HTML wins the verbosity award, and this output does not include .Dv XOF_XPATH or .Dv XOF_INFO data, which would expand the penultimate line to: .Bd -literal -offset indent
144
.Ed .Sh WHAT MAKES A GOOD FIELD NAME? To make useful, consistent field names, follow these guidelines: .Ss "Use lower case, even for TLAs" Lower case is more civilized. Even TLAs should be lower case to avoid scenarios where the differences between "XPath" and "Xpath" drive your users crazy. Using "xpath" is simpler and better. .Ss "Use hyphens, not underscores" Use of hyphens is traditional in XML, and the .Dv XOF_UNDERSCORES flag can be used to generate underscores in JSON, if desired. But the raw field name should use hyphens. .Ss "Use full words" Do not abbreviate especially when the abbreviation is not obvious or not widely used. Use "data\-size", not "dsz" or "dsize". Use "interface" instead of "ifname", "if\-name", "iface", "if", or "intf". .Ss "Use \-" Using the form \- or \-\- helps in making consistent, useful names, avoiding the situation where one app uses "sent\-packet" and another "packets\-sent" and another "packets\-we\-have\-sent". The can be dropped when it is obvious, as can obvious words in the classification. Use "receive\-after\-window\-packets" instead of "received\-packets\-of\-data\-after\-window". .Ss "Reuse existing field names" Nothing is worse than writing expressions like: .Bd -literal -offset indent if ($src1/process[pid == $pid]/name == $src2/proc\-table/proc/p[process\-id == $pid]/proc\-name) { ... } .Ed .Pp Find someone else who is expressing similar data and follow their fields and hierarchy. Remember the quote is not .Dq "Consistency is the hobgoblin of little minds" but .Dq "A foolish consistency is the hobgoblin of little minds" . .Ss "Think about your users" Have empathy for your users, choosing clear and useful fields that contain clear and useful data. You may need to augment the display content with .Xr xo_attr 3 calls or "{e:}" fields to make the data useful. .Ss "Do not use an arbitrary number postfix" What does "errors2" mean? No one will know. "errors\-after\-restart" would be a better choice. Think of your users, and think of the future. If you make "errors2", the next guy will happily make "errors3" and before you know it, someone will be asking what is the difference between errors37 and errors63. .Ss "Be consistent, uniform, unsurprising, and predictable" Think of your field vocabulary as an API. You want it useful, expressive, meaningful, direct, and obvious. You want the client application\(aqs programmer to move between without the need to understand a variety of opinions on how fields are named. They should see the system as a single cohesive whole, not a sack of cats. .Pp Field names constitute the means by which client programmers interact with our system. By choosing wise names now, you are making their lives better. .Pp After using .Xr xolint 1 to find errors in your field descriptors, use .Dq "xolint \-V" to spell check your field names and to detect different names for the same data. .Dq dropped\-short and .Dq dropped\-too\-short are both reasonable names, but using them both will lead users to ask the difference between the two fields. If there is no difference, use only one of the field names. If there is a difference, change the names to make that difference more obvious. .Sh SEE ALSO .Xr libxo 3 , .Xr xolint 1 , .Xr xo_emit 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_message.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_message.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_message.3 (revision 322022) @@ -1,68 +1,78 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_message , xo_message_c , xo_message_hc , xo_message_hcv .Nd emit messages in multiple output styles .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_message "const char *fmt" "..." .Ft void .Fn xo_message_e "const char *fmt" "..." .Ft void .Fn xo_message_c "int code" "const char *fmt" "..." .Ft void .Fn xo_message_hc "xo_handle_t *xop" "int code, const char *fmt" "..." .Ft void .Fn xo_message_hcv "xo_handle_t *xop" "int code" "const char *fmt" "va_list vap" .Sh DESCRIPTION .Nm xo_message generates text message which lack any sort of structure. These functions should not be used under normal conditions, since they completely defeat the value of using libxo. They are provided for scenarios when the output's content is genuinely unknown and unusable. It is used in converting programs where err/warn where not used, and error messages went to .Nm stdout , not .Nm stderr . Use of .Nm xo_message allows backwards compatibility with that output, but does not put the error in a useful form. .Pp The .Nm xo_message function generates output strings using the printf-style format string and arguments provided. If the format string does not end in a newline, .Nm xo_message_e will appear a colon, a space, and the error associated with the current .Nm errno value. .Nm xo_message_c behaves similarly for the value passed in the .Fa code parameter. .Nm xo_message_hc accepts a .Fa handle as opened by .Xr xo_create 3 and .Nm xo_message_hcv accepts a va_list parameter of arguments. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_no_setlocale.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_no_setlocale.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_no_setlocale.3 (revision 322022) @@ -1,43 +1,53 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_no_setlocale .Nd prevent implicit call to setlocale .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_no_setlocale "void" .Sh DESCRIPTION .Nm libxo automatically initializes the locale based on the setting of the environment variables .Ev LC_CTYPE , .Ev LANG , and .Ev LC_ALL . The first of this list of variables is used and if none of the variables are set, the locale defaults to .Em UTF-8 . The caller may wish to avoid this behavior, and can do so by calling the .Fn xo_no_setlocale function. .Sh SEE ALSO .Xr xo_emit 3 , .Xr xo_open_container 3 , .Xr xo_open_list 3 , .Xr xo_format 5 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_open_container.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_open_container.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_open_container.3 (revision 322022) @@ -1,188 +1,198 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_open_container , xo_open_container_h , xo_open_container_hd , xo_open_container_d .Nm xo_close_container , xo_close_container_h , xo_close_container_hd , xo_close_container_d .Nd open (and close) container constructs .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_open_container "const char *name" .Ft int .Fn xo_open_container_h "xo_handle_t *handle" "const char *name" .Ft int .Fn xo_open_container_hd "xo_handle_t *handle" "const char *name" .Ft int .Fn xo_open_container_d "const char *name" .Ft int .Fn xo_close_container "const char *name" .Ft int .Fn xo_close_container_h "xo_handle_t *handle" "const char *name" .Ft int .Fn xo_close_container_hd "xo_handle_t *handle" .Ft int .Fn xo_close_container_d "void" .Sh DESCRIPTION .Nm libxo represents two types of hierarchy: .Dq containers and .Dq lists . A container appears once under a given parent where a list contains instances that can appear multiple times. A container is used to hold related fields and to give the data organization and scope. The container has no value, but serves to contain other nodes. .Pp To open a container, call .Fn xo_open_container or .Fn xo_open_container_h . The former uses the default handle and the latter accepts a specific handle. .Pp To close a level, use the .Fn xo_close_container or .Fn xo_close_container_h functions. .Pp Each open call should have a matching close call. If the .Dv XOF_WARN flag is set and the name given does not match the name of the currently open container, a warning will be generated. .Bd -literal -offset indent -compact Example: xo_open_container("top"); xo_open_container("system"); xo_emit("{:host-name/%s%s%s", hostname, domainname ? "." : "", domainname ?: ""); xo_close_container("system"); xo_close_container("top"); Sample Output: Text: my-host.example.org XML: my-host.example.org JSON: "top" : { "system" : { "host-name": "my-host.example.org" } } HTML:
my-host.example.org
.Ed .Sh EMITTING HIERARCHY To create a container, use the .Fn xo_open_container and .Fn xo_close_container set of functions. The .Fa handle parameter contains a handle such as returned by .Xr xo_create 3 or .Dv NULL to use the default handle. The .Fa name parameter gives the name of the container, encoded in .Em UTF-8 . Since .Em ASCII is a proper subset of .Em UTF-8 , traditional C strings can be used directly. .Pp The close functions with the .Dq _d suffix are used in .Dq "Do The Right Thing" mode, where the name of the open containers, lists, and instances are maintained internally by .Nm libxo to allow the caller to avoid keeping track of the open container name. .Pp Use the .Dv XOF_WARN flag to generate a warning if the name given on the close does not match the current open container. .Pp For TEXT and HTML output, containers are not rendered into output text, though for HTML they are used when the .Dv XOF_XPATH flag is set. .Pp .Bd -literal -offset indent -compact EXAMPLE: xo_open_container("system"); xo_emit("The host name is {:host-name}\n", hn); xo_close_container("system"); XML: foo .Ed .Sh DTRT MODE Some users may find tracking the names of open containers, lists, and instances inconvenient. .Nm libxo offers a .Dq "Do The Right Thing" mode, where .Nm libxo will track the names of open containers, lists, and instances so the close function can be called without a name. To enable .Em DTRT mode, turn on the .Dv XOF_DTRT flag prior to making any other .Nm libxo output. .Bd -literal -offset indent -compact xo_set_flags(NULL, XOF_DTRT); .Ed Each open and close function has a version with the suffix .Dq _d , which will close the open container, list, or instance: .Bd -literal -offset indent -compact xo_open_container("top"); ... xo_close_container_d(); .Ed Note that the .Dv XOF_WARN flag will also cause .Nm libxo to track open containers, lists, and instances. A warning is generated when the name given to the close function and the name recorded do not match. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_open_list.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_open_list.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_open_list.3 (revision 322022) @@ -1,158 +1,168 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_open_list , xo_open_list_h , xo_open_list_hd , xo_open_list_d .Nm xo_open_instance , xo_open_instance_h , xo_open_instance_hd , xo_open_instance_d .Nm xo_close_instance , xo_close_instance_h , xo_close_instance_hd , xo_close_instance_d .Nm xo_close_list , xo_close_list_h , xo_close_list_hd , xo_close_list_d .Nd open and close lists and instances .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_open_list_h "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_open_list "const char *name" .Ft int .Fn xo_open_list_hd "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_open_list_d "const char *name" .Ft int .Fn xo_open_instance_h "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_open_instance "const char *name" .Ft int .Fn xo_open_instance_hd "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_open_instance_d "const char *name" .Ft int .Fn xo_close_instance_h "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_close_instance "const char *name" .Ft int .Fn xo_close_instance_hd "xo_handle_t *xop" .Ft int .Fn xo_close_instance_d "void" .Ft int .Fn xo_close_list_h "xo_handle_t *xop" "const char *name" .Ft int .Fn xo_close_list "const char *name" .Ft int .Fn xo_close_list_hd "xo_handle_t *xop" .Ft int .Fn xo_close_list_d "void" .Sh DESCRIPTION Lists are sequences of instances of homogeneous data objects. Two distinct levels of calls are needed to represent them in our output styles. Calls must be made to open and close a list, and for each instance of data in that list, calls must be make to open and close that instance. .Pp The name given to all calls must be identical, and it is strongly suggested that the name be singular, not plural, as a matter of style and usage expectations. .Pp A list is a set of one or more instances that appear under the same parent. The instances contain details about a specific object. One can think of instances as objects or records. A call is needed to open and close the list, while a distinct call is needed to open and close each instance of the list: .Bd -literal -offset indent -compact xo_open_list("item"); for (ip = list; ip->i_title; ip++) { xo_open_instance("item"); xo_emit("{L:Item} '{:name/%s}':\n", ip->i_title); xo_close_instance("item"); } xo_close_list("item"); .Ed Getting the list and instance calls correct is critical to the proper generation of XML and JSON data. .Pp .Bd -literal -offset indent -compact EXAMPLE: xo_open_list("user"); for (i = 0; i < num_users; i++) { xo_open_instance("user"); xo_emit("{k:name}:{:uid/%u}:{:gid/%u}:{:home}\n", pw[i].pw_name, pw[i].pw_uid, pw[i].pw_gid, pw[i].pw_dir); xo_close_instance("user"); } xo_close_list("user"); TEXT: phil:1001:1001:/home/phil pallavi:1002:1002:/home/pallavi XML: phil 1001 1001 /home/phil pallavi 1002 1002 /home/pallavi JSON: user: [ { "name": "phil", "uid": 1001, "gid": 1001, "home": "/home/phil", }, { "name": "pallavi", "uid": 1002, "gid": 1002, "home": "/home/pallavi", } ] .Ed .Pp .Sh LEAF LISTS In contrast to a list of instances, a "leaf list" is list of simple values. To emit a leaf list, call the .Fn xo_emit function using the ""l"" modifier: .Bd -literal -offset indent -compact for (ip = list; ip->i_title; ip++) { xo_emit("{Lwc:Item}{l:item}\n", ip->i_title); } .Ed .Pp The name of the field must match the name of the leaf list. .Pp In JSON, leaf lists are rendered as arrays of values. In XML, they are rendered as multiple leaf elements. .Bd -literal -offset indent -compact JSON: "item": "hammer", "nail" XML: hammer nail .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_open_marker.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_open_marker.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_open_marker.3 (revision 322022) @@ -1,105 +1,115 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, January 2015 .\" .Dd January 22, 2015 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_open_marker , xo_open_marker_h , xo_close_marker , xo_close_marker_h .Nd prevent and allow closing of open constructs .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_open_marker "const char *name" .Ft int .Fn xo_open_marker_h "xo_handle_t *handle" "const char *name" .Ft int .Fn xo_close_marker "const char *name" .Ft int .Fn xo_close_marker_h "xo_handle_t *handle" "const char *name" .Sh DESCRIPTION .Nm libxo represents hierarchy using two constructs: .Dq containers and .Dq lists . A marker can be used to affect how open constructs are closed, either by preventing their (implicit or explicit) closure or by forcing their closure. While a marker is open, no other open constructs can be closed. When a marker is closed, all constructs open since the marker was opened will be closed. A marker is used to "freeze" any open constructs. Calls to .Fn xo_close_* functions that would normally close them will be ignored, effectively blocking their closure. However when .Fn xo_close_marker is called, any containers, lists, or leaf-lists open since the matching .Fn xo_open_marker call will be close and the marker discarded. Markers use names which are not user-visible, allowing the caller to choose appropriate internal names. The marker has no value and is not emitted in any form. .Pp To open a marker, call .Fn xo_open_marker or .Fn xo_open_marker_h . The former uses the default handle and the latter accepts a specific handle. .Pp To close a marker, use the .Fn xo_close_marker or .Fn xo_close_marker_h functions. .Pp Each open call must have a matching close call. .Pp In this example, the .Fn xo_close_container call on line [1] will be ignored, since the open marker "outer" will prevent close of any open constructs that precede it. The .Fn xo_close_marker call on line [2] will close the "system" container, since it was opened after the "outer" marker. .Bd -literal -offset indent -compact Example: xo_open_container("top"); xo_open_marker("outer"); xo_open_container("system"); xo_emit("{:host-name/%s%s%s", hostname, domainname ? "." : "", domainname ?: ""); xo_close_container("top"); /* [1] */ xo_close_marker("outer"); /* [2] */ xo_close_container("top"); .Ed .Pp In this example, the code whiffles through a list of fish, calling a function to emit details about each fish. The marker "fish-guts" is used to ensure that any constructs opened by the function are closed properly. .Bd -literal -offset indent for (i = 0; fish[i]; i++) { xo_open_instance("fish"); xo_open_marker("fish-guts"); dump_fish_details(i); xo_close_marker("fish-guts"); } .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_options.7 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_options.7 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_options.7 (revision 322022) @@ -1,147 +1,156 @@ .\" # .\" # Copyright (c) 2014-2017, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd May 11, 2017 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_options .Nd common options for libxo\-based commands .Sh DESCRIPTION .Pp .Nm libxo allows the rendering of data into various output styles, including .Em text , .Em XML , .Em JSON , and .Em HTML . .Nm libxo uses command line options to trigger rendering behavior. Options are recognised in three forms: .Bl -bullet .It \-\-libxo .It \-\-libxo= .It \-\-libxo: .El .Pp The first two forms accept a comma\-separated set of words, detailed below, while the third form accepts a set of letters, also below. The triggered functionality is identical. .Bl -column "Token2341234" .It Sy "Option " "Action" .It "color " "Enable colors/effects for display styles (TEXT, HTML)" .It "flush " "Flush after each emit call" .It "flush\-line " "Flush each line of output" .It "html " "Emit HTML output" .It "indent=xx " "Set the indentation level" .It "info " "Add info attributes (HTML)" .It "json " "Emit JSON output" .It "keys " "Emit the key attribute for keys (XML)" .It "log\-gettext" "Log (via stderr) each gettext(3) string lookup" .It "log\-syslog " "Log (via stderr) each syslog message (via xo_syslog)" .It "no\-humanize" "Ignore the {h:} modifier (TEXT, HTML)" .It "no\-locale " "Do not initialize the locale setting" .It "no\-retain " "Prevent retaining formatting information" .It "pretty " "Emit pretty\-printed output" .It "retain " "Force retaining formatting information" .It "text " "Emit TEXT output" .It "underscores" "Replace XML\-friendly \"\-\"s with JSON friendly \"_\"s" .It "units " "Add the 'units' (XML) or 'data\-units (HTML) attribute" .It "warn " "Emit warnings when libxo detects bad calls" .It "warn\-xml " "Emit warnings in XML" .It "xml " "Emit XML output" .It "xpath " "Add XPath expressions (HTML)" .El .Pp The brief options are a set of single\-letter aliases for the longer terms, used as a single string: .Bl -column "Value" "Equivalent Token" .It Sy "Value" "Equivalent Token" .It "c .It "f " "flush" .It "F " "flush\-line" .It "H " "html" .It "I " "info" .It "i" "indent=" .It "J " "json" .It "k " "keys" .It "n " "no\-humanize" .It "P " "pretty" .It "T " "text" .It "U " "units" .It "u " "underscore .It "W " "warn" .It "X " "xml" .It "x " "xpath" .El .Pp Most of these option are simple and direct, but some require additional details: .Pp .Fa "flush\-line" performs line buffering, even when the output is not directed to a TTY device. .Pp .Fa info generates additional data for HTML, encoded in attributes using names that state with "data\-". .Pp .Fa keys adds a "key" attribute for XML output to indicate that a leaf is an identifier for the list member. .Pp .Fa no\-humanize avoids "humanizing" numeric output (see .Xr humanize_number 3 for details). .Pp .Fa no\-locale instructs .Nm libxo to avoid translating output to the current locale. .Pp .Fa no\-retain disables the ability of .Nm libxo to internally retain "compiled" information about formatting strings. .Pp .Fa underscores can be used with .Em JSON output to change .Em XML \-friendly names with dashes into .Em JSON \-friendly name with underscores. .Pp .Fa warn allows .Nm libxo to emit warnings on stderr when application code make incorrect calls. .Fa warn\-xml causes those warnings to be placed in .Em XML inside the output. .Sh EXAMPLES The following are three example invocations of .Xr ps 1 : .Bd -literal ps \-\-libxo json,pretty,warn \-ux ps \-\-libxo=xml \-lg ps \-\-libxo:Hxc 1 .Ed .Sh SEE ALSO .Xr libxo 3 , .Xr xo_format 5 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_parse_args.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_parse_args.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_parse_args.3 (revision 322022) @@ -1,152 +1,162 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_parse_args , xo_set_program .Nd detect, parse, and remove arguments for libxo .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_parse_args "int argc" "char **argv" .Ft int .Fn xo_set_program "const char *name" .Sh DESCRIPTION The .Fn xo_parse_args function is used to process command-line arguments. .Nm libxo specific options are processed and removed from the argument list so the calling application does not need to process them. If successful, a new value for argc is returned. On failure, a message it emitted and -1 is returned. .Bd -literal -offset indent argc = xo_parse_args(argc, argv); if (argc < 0) exit(EXIT_FAILURE); .Ed .Pp Following the call to .Fn xo_parse_args , the application can process the remaining arguments in a normal manner. .Pp .Nm libxo uses command line options to trigger rendering behavior. The following options are recognised: .Pp .Bl -tag -width "--libxo" .It \-\^\-libxo .It \-\^\-libxo= .It \-\^\-libxo: .El .Pp Options is a comma-separated list of tokens that correspond to output styles, flags, or features: .Pp .Bl -tag -width "12345678" .It Sy "Token Action" .It Dv dtrt Enable "Do The Right Thing" mode .It Dv html Emit HTML output .It Dv indent=xx Set the indentation level .It Dv info Add info attributes (HTML) .It Dv json Emit JSON output .It Dv keys Emit the key attribute for keys (XML) .It Dv log-gettext Log (via stderr) each .Xr gettext 3 string lookup .It Dv log-syslog Log (via stderr) each syslog message (via .Xr xo_syslog 3 ) .If Dv no-humanize Ignore the {h:} modifier (TEXT, HTML) .It Dv no-locale Do not initialize the locale setting .It Dv no-retain Prevent retaining formatting information .It Dv no-top Do not emit a top set of braces (JSON) .It Dv not-first Pretend the 1st output item was not 1st (JSON) .It Dv pretty Emit pretty-printed output .It Dv retain Force retaining formatting information .It Dv text Emit TEXT output .If Dv underscores Replace XML-friendly "-"s with JSON friendly "_"s e .It Dv units Add the 'units' (XML) or 'data-units (HTML) attribute .It Dv warn Emit warnings when libxo detects bad calls .It Dv warn-xml Emit warnings in XML .It Dv xml Emit XML output .It Dv xpath Add XPath expressions (HTML) .El .Pp The .Dq brief-options are single letter commands, designed for those with too little patience to use real tokens. No comma separator is used. .Bl -column "i" .It Sy "Token Action" .It "H " "Enable HTML output (XO_STYLE_HTML)" .It "I " "Enable info output (XOF_INFO)" .It "i " "Indent by " .It "J " "Enable JSON output (XO_STYLE_JSON)" .It "P " "Enable pretty-printed output (XOF_PRETTY)" .It "T " "Enable text output (XO_STYLE_TEXT)" .It "W " "Enable warnings (XOF_WARN)" .It "X " "Enable XML output (XO_STYLE_XML)" .It "x " "Enable XPath data (XOF_XPATH)" .El .Pp The .Fn xo_set_program function sets name of the program as reported by functions like .Fn xo_failure , .Fn xo_warn , .Fn xo_err , etc. The program name is initialized by .Fn xo_parse_args , but subsequent calls to .Fn xo_set_program can override this value. .Pp Note that the value is not copied, so the memory passed to .Fn xo_set_program (and .Fn xo_parse_args ) must be maintained by the caller. .Pp .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_allocator.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_allocator.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_allocator.3 (revision 322022) @@ -1,54 +1,64 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_allocator .Nd set allocation functions for libxo .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Sy typedef void *(*xo_realloc_func_t)(void *, size_t); .Pp .Sy typedef void (*xo_free_func_t)(void *); .Ft void .Fn xo_set_allocator "xo_realloc_func_t realloc_func" "xo_free_func_t free_func" .Sh DESCRIPTION The .Fn xo_set_allocator function allows .Nm libxo to be used in environments where the standard .Xr realloc 3 and .Xr free 3 functions are not available. .Pp .Fa realloc_func should expect the same arguments as .Xr realloc 3 and return a pointer to memory following the same convention. .Fa free_func will receive the same argument as .Xr free 3 and should release it, as appropriate for the environment. .Pp By default, the standard .Xr realloc 3 and .Xr free 3 functions are used. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_flags.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_flags.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_flags.3 (revision 322022) @@ -1,139 +1,149 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_flags , xo_clear_flags .Nd set operational flags for a libxo handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_set_flags "xo_handle_t *handle" "unsigned flags" .Ft void .Fn xo_clear_flags "xo_handle_t *handle" "xo_xof_flags_t flags" .Sh DESCRIPTION Use the .Fn xo_set_flags function to set the flags for a .Nm libxo handle. To use the default handle, pass a .Dv NULL handle. .Pp The set of valid flags include: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" .It Dv XOF_CLOSE_FP Close file pointer on .Xr xo_destroy 3 . This flag will trigger the call of the .Fn close_func (provided via .Xr xo_set_writer 3 ) when the handle is destroyed. .It Dv XOF_COLOR Enable color and effects in output regardless of output device. .It Dv XOF_COLOR_ALLOWED Allow color and effects if the output device is a terminal. .It Dv XOF_INFO Display info data attributes (HTML) .It Dv XOF_KEYS Emit the key attribute (XML) .It Dv XOF_LOG_GETTEXT Log (via stderr) each .Xr gettext 3 string lookup .It Dv XOF_LOG_SYSLOG Log (via stderr) each syslog message (via .Xr xo_syslog 3 ) .It Dv XOF_NO_ENV Do not use the .Ev LIBXO_OPTIONS environment variable. .It Dv XOF_PRETTY Make 'pretty printed' output, with the addition of indentation and newlines to enhance the readability of XML, JSON, and HTML output. Text output is not affected. .It Dv XOF_UNDERSCORES Replaces hyphens with underscores .It Dv XOF_UNITS Display units (XML and HMTL) .It Dv XOF_WARN Generate warnings for broken calls, triggering diagnostic output (on standard error) when the library notices errors during operations, or with arguments to functions. Without warnings enabled, such conditions are ignored. Warnings allow developers to debug their interaction with .Nm libxo . The function .Fn xo_failure can be used as a breakpoint for a debugger, regardless of whether warnings are enabled. .It Dv XOF_WARN_XML Generate warnings in XML on stdout .It Dv XOF_XPATH Emit XPath expressions (HTML) .It Dv XOF_COLUMNS Force .Xr xo_emit 3 to return columns used .It Dv XOF_FLUSH Flush output after each .Xr xo_emit 3 call .El .Pp If the style is .Dv XO_STYLE_HTML , the following additional flags can be used: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" .It Dv XOF_XPATH Emit "data-xpath" attributes .It Dv XOF_INFO Emit additional informational fields for HTML output. See .Xr xo_set_info 3 for details. .El .Pp The .Dv XOF_XPATH flag enables the emission of XPath expressions detailing the hierarchy of XML elements used to encode the data field, if the XPATH style of output were requested. .Pp If the style is .Dv XO_STYLE_XML , the following additional flags can be used: .Bl -tag -width "XOF_UNDERSCORES" .It Sy "Flag Description" .It XOF_KEYS Add 'key' attribute to the XML encoding for field definitions that use the 'k' modifier. The key attribute has the value "key". .El .Pp The .Fn xo_clear_flags function turns off the given flags in a specific handle. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_info.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_info.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_info.3 (revision 322022) @@ -1,102 +1,112 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_info .Nd set the field information data for libxo .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_set_info "xo_handle_t *handle" "xo_info_t *info" "int count" .Sh DESCRIPTION HTML data can include additional information in attributes that begin with "data-". To enable this, three things must occur: .Pp First the application must build an array of .Dv xo_info_t structures, one per tag. The array must be sorted by name, since .Nm libxo uses a binary search to find the entry that matches names from format instructions. .Pp The .Dv xo_info_t structure is defined in .In libxo/xo.h : .Bd -literal -offset indent typedef struct xo_info_s { const char *xi_name; /* Name of the element */ const char *xi_type; /* Type of field */ const char *xi_help; /* Description of field */ } xo_info_t; .Ed .Pp Second, the application must inform .Nm libxo about this information using the .Fn xo_set_info call. Like other .Nm libxo calls, passing .Dv NULL for the handle tells .Nm libxo to use the default handle. .Pp If the .Fa count is -1, .Nm libxo will count the elements of .Fa info , but there must be an empty element at the end. More typically, the number is known to the application: .Bd -literal -offset indent xo_info_t info[] = { { "in-stock", "number", "Number of items in stock" }, { "name", "string", "Name of the item" }, { "on-order", "number", "Number of items on order" }, { "sku", "string", "Stock Keeping Unit" }, { "sold", "number", "Number of items sold" }, }; int info_count = (sizeof(info) / sizeof(info[0])); ... xo_set_info(NULL, info, info_count); .Ed .Pp Third, the emission of info must be triggered with the .Dv XOF_INFO flag using either the .Fn xo_set_flags function or the .Dq --libxo=info command line argument. .Pp The type and help values, if present, are emitted as the "data-type" and "data-help" attributes: .Bd -literal -offset indent
GRO-000-533
.Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_options.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_options.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_options.3 (revision 322022) @@ -1,31 +1,41 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_options .Nd change options used by a libxo handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft int .Fn xo_set_options "xo_handle_t *xop" "const char *input" .Sh DESCRIPTION The .Fn xo_set_options function accepts a comma-separated list of styles and flags and enables them for a specific handle. The options are identical to those listed in .Xr xo_parse_args 3 . .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_style.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_style.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_style.3 (revision 322022) @@ -1,53 +1,63 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_style , xo_set_style_name .Nd set the output style for a libxo handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_set_style "xo_handle_t *handle" "unsigned style" .Ft int .Fn xo_set_style_name "xo_handle_t *handle" "const char *style" .Sh DESCRIPTION Use the .Fn xo_set_style function to set the output style for a handle. To use the default handle, pass a .Dv NULL handle. The set of output styles used by .Nm libxo is: .Bl -column "XO_STYLE_TEXT12" .It Sy "Flag Description" .It "XO_STYLE_TEXT Traditional text output" .It "XO_STYLE_XML XML encoded data" .It "XO_STYLE_JSON JSON encoded data" .It "XO_STYLE_HTML HTML encoded data" .El .Pp The .Fn xo_set_style_name function can be used to set the style based on a name encoded as a string. The name can be any of the styles: "text", "xml", "json", or "html". .Bd -literal -offset indent EXAMPLE: xo_set_style_name(NULL, "html"); .Ed .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_syslog_enterprise_id.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_syslog_enterprise_id.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_syslog_enterprise_id.3 (revision 322022) @@ -1,36 +1,46 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2015 .\" .Dd July 20, 2015 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_syslog_enterprise_id .Nd Set the enterprise identifier for syslog content .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_set_syslog_enterprise_id "unsigned short eid" .Ft void .Sh DESCRIPTION The .Fn xo_set_syslog_enterprise_id function records an enterprise identifier used for subsequent .Xr xo_syslog 3 calls. Enterprise IDs are defined by IANA, the Internet Assigned Numbers Authority: .Bd -literal -offset indent https://www.iana.org/assignments/enterprise-numbers/enterprise-numbers .Ed .Sh SEE ALSO .Xr xo_syslog 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_version.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_version.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_version.3 (revision 322022) @@ -1,34 +1,44 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_version , xo_set_version_h .Nd record content-version information in encoded output .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_set_version "const char *version" .Ft void .Fn xo_set_version_h "xo_handle_t *xop" "const char *version" .Sh DESCRIPTION The .Nm xo_set_version function records a version number to be emitted as part of the data for encoding styles (XML and JSON). This version number is suitable for tracking changes in the content, allowing a user of the data to discern which version of the data model is in use. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_set_writer.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_set_writer.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_set_writer.3 (revision 322022) @@ -1,56 +1,66 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_set_writer .Nd set custom writer functions for a libxo handle .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Sy typedef int (*xo_write_func_t)(void *, const char *); .Pp .Sy typedef void (*xo_close_func_t)(void *); .Pp .Sy typedef int (*xo_flush_func_t)(void *); .Fn xo_set_writer "xo_handle_t *handle" "void *opaque" "xo_write_func_t write_func" "xo_close_func_t close_func" "xo_flush_func_t flush_func" .Sh DESCRIPTION The .Fn xo_set_writer function allows custom .Dq write functions which can tailor how .Nm libxo writes data. An .Fa opaque argument is recorded and passed back to the .Fa write_func function, allowing the function to acquire context information. The .Fa close_func function can release this opaque data and any other resources as needed. The .Fa flush_func function should flush any pending data associated with the opaque pointer. .Sh SEE ALSO .Xr xo_emit 3 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/libxo/xo_syslog.3 =================================================================== --- projects/make-check-sandbox/contrib/libxo/libxo/xo_syslog.3 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/libxo/xo_syslog.3 (revision 322022) @@ -1,79 +1,89 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2015 .\" .Dd July 20, 2015 .Dt LIBXO 3 .Os .Sh NAME .Nm xo_syslog , xo_vsyslog , xo_open_log , xo_close_log , xo_set_logmask .Nd create SYSLOG (RFC5424) log records using libxo formatting .Sh LIBRARY .Lb libxo .Sh SYNOPSIS .In libxo/xo.h .Ft void .Fn xo_syslog "int pri" "const char *name" "const char *fmt" "..." .Ft void .Fn xo_vsyslog "int pri" "const char *name" "const char *fmt" "va_list vap" .Ft void .Fn xo_close_log "void" .Ft void .Fn xo_open_log "const char *ident" "int logstat" "int logfac" .Ft int .Fn xo_set_logmask "int pmask" .Sh DESCRIPTION The .Fn xo_syslog function creates log entries following the standard defined in RFC5424. These messages are sent to the log .Xr syslogd 8 daemon, where they can be filtered, forwarded, and archived. .Nm libxo format strings are used to create both the message text and the .Nm SD-PARAMS content, containing name/value pairs that can be parsed by suitable automation software. .Pp Refer to .Xr xo_format 5 for basic information about formatting strings. .Nm xo_syslog encodes all value fields at SD-PARAMS within the syslog message. An exception is made for fields with the "{d:}" modifier; such fields appear in the message text only, with fields with the "{e:}" modifier appear as SD-PARAMS, but not in the message text. .Pp .Fn xo_vsyslog accepts a .Fa va_list for additional flexibility. .Pp .Fn xo_open_log , .Fn xo_close_log , and .Fn xo_set_logmask are all analogous to their libs counterparts, .Xr openlog 3 , .Xr closelog 3 , and .Xr setlogmask 3 . The extra underscores in the names are unfortunate, but keep consistency in .Nm libxo function names. .Sh EXAMPLES .Bd -literal -offset indent xo_syslog(LOG_LOCAL4 | LOG_NOTICE, "ID47", "{e:iut/%u}An {:event-source} {:event-id/%u} log entry", iut, source, id); .Ed .Sh SEE ALSO .Xr xo_syslog 3 , .Xr xo_set_syslog_enterprise_id 3 , .Xr xo_format 5 , .Xr libxo 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.E.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.E.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.E.out (revision 322022) @@ -1,143 +1,149 @@ op create: [] [] [0] op open_container: [top] [] [0x810] +op content: [address] [0x0] [0] +op content: [port] [1] [0] +op content: [address] [0x0] [0] +op content: [port] [1] [0] +op content: [address] [0x0] [0] +op content: [port] [1] [0] op content: [used-percent] [12] [0] op content: [kve_start] [0xdeadbeef] [0x8] op content: [kve_end] [0xcabb1e] [0x8] op string: [host] [my-box] [0x200000] op string: [domain] [example.com] [0x200000] op string: [host] [my-box] [0x200008] op string: [domain] [example.com] [0x200000] op string: [label] [value] [0x200000] op string: [max-chaos] [very] [0x1000] op content: [min-chaos] [42] [0] op string: [some-chaos] [[42]] [0] op string: [host] [my-box] [0] op string: [domain] [example.com] [0] op attr: [test] [value] [0] op open_container: [data] [] [0x810] op open_list: [item] [] [0] op attr: [test2] [value2] [0] op open_instance: [item] [] [0x810] op attr: [test3] [value3] [0] op string: [sku] [GRO-000-415] [0x98] op string: [name] [gum] [0x80] op content: [sold] [1412] [0x20] op content: [in-stock] [54] [0] op content: [on-order] [10] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op attr: [test3] [value3] [0] op string: [sku] [HRD-000-212] [0x98] op string: [name] [rope] [0x80] op content: [sold] [85] [0x20] op content: [in-stock] [4] [0] op content: [on-order] [2] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op attr: [test3] [value3] [0] op string: [sku] [HRD-000-517] [0x98] op string: [name] [ladder] [0x80] op content: [sold] [0] [0x20] op content: [in-stock] [2] [0] op content: [on-order] [1] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op attr: [test3] [value3] [0] op string: [sku] [HRD-000-632] [0x98] op string: [name] [bolt] [0x80] op content: [sold] [4123] [0x20] op content: [in-stock] [144] [0] op content: [on-order] [42] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op attr: [test3] [value3] [0] op string: [sku] [GRO-000-2331] [0x98] op string: [name] [water] [0x80] op content: [sold] [17] [0x20] op content: [in-stock] [14] [0] op content: [on-order] [2] [0] op close_instance: [item] [] [0] op close_list: [item] [] [0] op close_container: [data] [] [0] op open_container: [data2] [] [0x810] op open_list: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [GRO-000-415] [0x98] op string: [name] [gum] [0x80] op content: [sold] [1412.0] [0x20] op content: [in-stock] [54] [0] op content: [on-order] [10] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [HRD-000-212] [0x98] op string: [name] [rope] [0x80] op content: [sold] [85.0] [0x20] op content: [in-stock] [4] [0] op content: [on-order] [2] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [HRD-000-517] [0x98] op string: [name] [ladder] [0x80] op content: [sold] [0] [0x20] op content: [in-stock] [2] [0] op content: [on-order] [1] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [HRD-000-632] [0x98] op string: [name] [bolt] [0x80] op content: [sold] [4123.0] [0x20] op content: [in-stock] [144] [0] op content: [on-order] [42] [0] op close_instance: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [GRO-000-2331] [0x98] op string: [name] [water] [0x80] op content: [sold] [17.0] [0x20] op content: [in-stock] [14] [0] op content: [on-order] [2] [0] op close_instance: [item] [] [0] op close_list: [item] [] [0] op close_container: [data2] [] [0] op open_container: [data3] [] [0x810] op open_list: [item] [] [0] op open_instance: [item] [] [0x810] op string: [sku] [GRO-000-533] [0x98] op string: [name] [fish] [0x80] op content: [sold] [1321.0] [0x20] op content: [in-stock] [45] [0] op content: [on-order] [1] [0] op close_instance: [item] [] [0] op close_list: [item] [] [0] op close_container: [data3] [] [0] op open_container: [data4] [] [0x810] op open_list: [item] [] [0] op attr: [test4] [value4] [0] op string: [item] [gum] [0x2000] op attr: [test4] [value4] [0] op string: [item] [rope] [0x2000] op attr: [test4] [value4] [0] op string: [item] [ladder] [0x2000] op attr: [test4] [value4] [0] op string: [item] [bolt] [0x2000] op attr: [test4] [value4] [0] op string: [item] [water] [0x2000] op close_list: [item] [] [0] op close_container: [data4] [] [0] op content: [cost] [425] [0] op content: [cost] [455] [0] op string: [mode] [mode] [0x8] op string: [mode_octal] [octal] [0x8] op string: [links] [links] [0x1000] op string: [user] [user] [0x1000] op string: [group] [group] [0x1000] op string: [pre] [that] [0x8] op content: [links] [3] [0x1000] op string: [post] [this] [0x1000] op string: [mode] [/some/file] [0x1000] op content: [mode_octal] [640] [0x8] op content: [links] [1] [0x1000] op string: [user] [user] [0x1000] op string: [group] [group] [0x1000] op close_container: [top] [] [0] op finish: [] [] [0] op flush: [] [] [0] Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.H.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.H.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.H.out (revision 322022) @@ -1,2 +1,2 @@ -
df
12
%
testing argument modifier
my-box
.
example.com
...
testing argument modifier with encoding to
.
example.com
...
Label text
value
very
42
42 +
anchor
0x0
..
1
anchor
0x0
..
1
anchor
0x0
..
1
df
12
%
testing argument modifier
my-box
.
example.com
...
testing argument modifier with encoding to
.
example.com
...
Label text
value
very
42
42
Connecting to
my-box
.
example.com
...
Item
Total Sold
In Stock
On Order
SKU
gum
1412
54
10
GRO-000-415
rope
85
4
2
HRD-000-212
ladder
0
2
1
HRD-000-517
bolt
4123
144
42
HRD-000-632
water
17
14
2
GRO-000-2331
Item
'
gum
':
Total sold
:
1412.0
In stock
:
54
On order
:
10
SKU
:
GRO-000-415
Item
'
rope
':
Total sold
:
85.0
In stock
:
4
On order
:
2
SKU
:
HRD-000-212
Item
'
ladder
':
Total sold
:
0
In stock
:
2
On order
:
1
SKU
:
HRD-000-517
Item
'
bolt
':
Total sold
:
4123.0
In stock
:
144
On order
:
42
SKU
:
HRD-000-632
Item
'
water
':
Total sold
:
17.0
In stock
:
14
On order
:
2
SKU
:
GRO-000-2331
Item
'
fish
':
Total sold
:
1321.0
In stock
:
45
On order
:
1
SKU
:
GRO-000-533
Item
:
gum
Item
:
rope
Item
:
ladder
Item
:
bolt
Item
:
water
X
X
X
X
X
X
X
X
X
X
Cost
:
425
X
X
Cost
:
455
links
user
group
3
this
/some/file
1
user
group
\ No newline at end of file Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HIPx.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HIPx.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HIPx.out (revision 322022) @@ -1,353 +1,374 @@
+
anchor
+
+
0x0
+
..
+
1
+
+
+
anchor
+
+
0x0
+
..
+
1
+
+
+
anchor
+
+
0x0
+
..
+
1
+
+
df
12
%
testing argument modifier
my-box
.
example.com
...
testing argument modifier with encoding to
.
example.com
...
Label text
value
very
42
42
Connecting to
my-box
.
example.com
...
Item
Total Sold
In Stock
On Order
SKU
gum
1412
54
10
GRO-000-415
rope
85
4
2
HRD-000-212
ladder
0
2
1
HRD-000-517
bolt
4123
144
42
HRD-000-632
water
17
14
2
GRO-000-2331
Item
'
gum
':
Total sold
:
1412.0
In stock
:
54
On order
:
10
SKU
:
GRO-000-415
Item
'
rope
':
Total sold
:
85.0
In stock
:
4
On order
:
2
SKU
:
HRD-000-212
Item
'
ladder
':
Total sold
:
0
In stock
:
2
On order
:
1
SKU
:
HRD-000-517
Item
'
bolt
':
Total sold
:
4123.0
In stock
:
144
On order
:
42
SKU
:
HRD-000-632
Item
'
water
':
Total sold
:
17.0
In stock
:
14
On order
:
2
SKU
:
GRO-000-2331
Item
'
fish
':
Total sold
:
1321.0
In stock
:
45
On order
:
1
SKU
:
GRO-000-533
Item
:
gum
Item
:
rope
Item
:
ladder
Item
:
bolt
Item
:
water
X
X
X
X
X
X
X
X
X
X
Cost
:
425
X
X
Cost
:
455
links
user
group
3
this
/some/file
1
user
group
Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.HP.out (revision 322022) @@ -1,353 +1,374 @@
+
anchor
+
+
0x0
+
..
+
1
+
+
+
anchor
+
+
0x0
+
..
+
1
+
+
+
anchor
+
+
0x0
+
..
+
1
+
+
df
12
%
testing argument modifier
my-box
.
example.com
...
testing argument modifier with encoding to
.
example.com
...
Label text
value
very
42
42
Connecting to
my-box
.
example.com
...
Item
Total Sold
In Stock
On Order
SKU
gum
1412
54
10
GRO-000-415
rope
85
4
2
HRD-000-212
ladder
0
2
1
HRD-000-517
bolt
4123
144
42
HRD-000-632
water
17
14
2
GRO-000-2331
Item
'
gum
':
Total sold
:
1412.0
In stock
:
54
On order
:
10
SKU
:
GRO-000-415
Item
'
rope
':
Total sold
:
85.0
In stock
:
4
On order
:
2
SKU
:
HRD-000-212
Item
'
ladder
':
Total sold
:
0
In stock
:
2
On order
:
1
SKU
:
HRD-000-517
Item
'
bolt
':
Total sold
:
4123.0
In stock
:
144
On order
:
42
SKU
:
HRD-000-632
Item
'
water
':
Total sold
:
17.0
In stock
:
14
On order
:
2
SKU
:
GRO-000-2331
Item
'
fish
':
Total sold
:
1321.0
In stock
:
45
On order
:
1
SKU
:
GRO-000-533
Item
:
gum
Item
:
rope
Item
:
ladder
Item
:
bolt
Item
:
water
X
X
X
X
X
X
X
X
X
X
Cost
:
425
X
X
Cost
:
455
links
user
group
3
this
/some/file
1
user
group
Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.J.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.J.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.J.out (revision 322022) @@ -1,2 +1,2 @@ -{"top": {"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"} +{"top": {"address":"0x0","port":1,"address":"0x0","port":1,"address":"0x0","port":1,"used-percent":12,"kve_start":"0xdeadbeef","kve_end":"0xcabb1e","host":"my-box","domain":"example.com","host":"my-box","domain":"example.com","label":"value","max-chaos":"very","min-chaos":42,"some-chaos":"[42]","host":"my-box","domain":"example.com", "data": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17,"in-stock":14,"on-order":2}]}, "data2": {"item": [{"sku":"GRO-000-415","name":"gum","sold":1412.0,"in-stock":54,"on-order":10}, {"sku":"HRD-000-212","name":"rope","sold":85.0,"in-stock":4,"on-order":2}, {"sku":"HRD-000-517","name":"ladder","sold":0,"in-stock":2,"on-order":1}, {"sku":"HRD-000-632","name":"bolt","sold":4123.0,"in-stock":144,"on-order":42}, {"sku":"GRO-000-2331","name":"water","sold":17.0,"in-stock":14,"on-order":2}]}, "data3": {"item": [{"sku":"GRO-000-533","name":"fish","sold":1321.0,"in-stock":45,"on-order":1}]}, "data4": {"item": ["gum","rope","ladder","bolt","water"]},"cost":425,"cost":455,"mode":"mode","mode_octal":"octal","links":"links","user":"user","group":"group","pre":"that","links":3,"post":"this","mode":"/some/file","mode_octal":640,"links":1,"user":"user","group":"group"} } Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.JP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.JP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.JP.out (revision 322022) @@ -1,130 +1,136 @@ { "top": { + "address": "0x0", + "port": 1, + "address": "0x0", + "port": 1, + "address": "0x0", + "port": 1, "used-percent": 12, "kve_start": "0xdeadbeef", "kve_end": "0xcabb1e", "host": "my-box", "domain": "example.com", "host": "my-box", "domain": "example.com", "label": "value", "max-chaos": "very", "min-chaos": 42, "some-chaos": "[42]", "host": "my-box", "domain": "example.com", "data": { "item": [ { "sku": "GRO-000-415", "name": "gum", "sold": 1412, "in-stock": 54, "on-order": 10 }, { "sku": "HRD-000-212", "name": "rope", "sold": 85, "in-stock": 4, "on-order": 2 }, { "sku": "HRD-000-517", "name": "ladder", "sold": 0, "in-stock": 2, "on-order": 1 }, { "sku": "HRD-000-632", "name": "bolt", "sold": 4123, "in-stock": 144, "on-order": 42 }, { "sku": "GRO-000-2331", "name": "water", "sold": 17, "in-stock": 14, "on-order": 2 } ] }, "data2": { "item": [ { "sku": "GRO-000-415", "name": "gum", "sold": 1412.0, "in-stock": 54, "on-order": 10 }, { "sku": "HRD-000-212", "name": "rope", "sold": 85.0, "in-stock": 4, "on-order": 2 }, { "sku": "HRD-000-517", "name": "ladder", "sold": 0, "in-stock": 2, "on-order": 1 }, { "sku": "HRD-000-632", "name": "bolt", "sold": 4123.0, "in-stock": 144, "on-order": 42 }, { "sku": "GRO-000-2331", "name": "water", "sold": 17.0, "in-stock": 14, "on-order": 2 } ] }, "data3": { "item": [ { "sku": "GRO-000-533", "name": "fish", "sold": 1321.0, "in-stock": 45, "on-order": 1 } ] }, "data4": { "item": [ "gum", "rope", "ladder", "bolt", "water" ] }, "cost": 425, "cost": 455, "mode": "mode", "mode_octal": "octal", "links": "links", "user": "user", "group": "group", "pre": "that", "links": 3, "post": "this", "mode": "/some/file", "mode_octal": 640, "links": 1, "user": "user", "group": "group" } } Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.T.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.T.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.T.out (revision 322022) @@ -1,55 +1,58 @@ +anchor 0x0..1 +anchor 0x0..1 +anchor 0x0..1 df 12% testing argument modifier my-box.example.com... testing argument modifier with encoding to .example.com... Label text value very 4242 Connecting to my-box.example.com... Item Total Sold In Stock On Order SKU gum 1412 54 10 GRO-000-415 rope 85 4 2 HRD-000-212 ladder 0 2 1 HRD-000-517 bolt 4123 144 42 HRD-000-632 water 17 14 2 GRO-000-2331 Item 'gum': Total sold: 1412.0 In stock: 54 On order: 10 SKU: GRO-000-415 Item 'rope': Total sold: 85.0 In stock: 4 On order: 2 SKU: HRD-000-212 Item 'ladder': Total sold: 0 In stock: 2 On order: 1 SKU: HRD-000-517 Item 'bolt': Total sold: 4123.0 In stock: 144 On order: 42 SKU: HRD-000-632 Item 'water': Total sold: 17.0 In stock: 14 On order: 2 SKU: GRO-000-2331 Item 'fish': Total sold: 1321.0 In stock: 45 On order: 1 SKU: GRO-000-533 Item: gum Item: rope Item: ladder Item: bolt Item: water XXXXXXXX X XCost: 425 X XCost: 455 links user group 3 this /some/file 1 user group Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.X.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.X.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.X.out (revision 322022) @@ -1 +1 @@ -120xdeadbeef0xcabb1emy-boxexample.commy-boxexample.comvery42[42]my-boxexample.comGRO-000-415gum14125410HRD-000-212rope8542HRD-000-517ladder021HRD-000-632bolt412314442GRO-000-2331water17142GRO-000-415gum1412.05410HRD-000-212rope85.042HRD-000-517ladder021HRD-000-632bolt4123.014442GRO-000-2331water17.0142GRO-000-533fish1321.0451gumropeladderboltwater425455modeoctallinksusergroup
that
3this/some/file6401usergroup
\ No newline at end of file +
0x0
1
0x0
1
0x0
1120xdeadbeef0xcabb1emy-boxexample.commy-boxexample.comvery42[42]my-boxexample.comGRO-000-415gum14125410HRD-000-212rope8542HRD-000-517ladder021HRD-000-632bolt412314442GRO-000-2331water17142GRO-000-415gum1412.05410HRD-000-212rope85.042HRD-000-517ladder021HRD-000-632bolt4123.014442GRO-000-2331water17.0142GRO-000-533fish1321.0451gumropeladderboltwater425455modeoctallinksusergroup
that
3this/some/file6401usergroup
\ No newline at end of file Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.XP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.XP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_01.XP.out (revision 322022) @@ -1,120 +1,126 @@ +
0x0
+ 1 +
0x0
+ 1 +
0x0
+ 1 12 0xdeadbeef 0xcabb1e my-box example.com my-box example.com very 42 [42] my-box example.com GRO-000-415 gum 1412 54 10 HRD-000-212 rope 85 4 2 HRD-000-517 ladder 0 2 1 HRD-000-632 bolt 4123 144 42 GRO-000-2331 water 17 14 2 GRO-000-415 gum 1412.0 54 10 HRD-000-212 rope 85.0 4 2 HRD-000-517 ladder 0 2 1 HRD-000-632 bolt 4123.0 144 42 GRO-000-2331 water 17.0 14 2 GRO-000-533 fish 1321.0 45 1 gum rope ladder bolt water 425 455 mode octal links user group
that
3 this /some/file 640 1 user group
Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.E.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.E.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.E.out (revision 322022) @@ -1,68 +1,68 @@ op create: [] [] [0] op open_container: [top] [] [0x40010] op open_container: [data] [] [0x40010] op string: [what] [braces] [0] op string: [length] [abcdef] [0] op content: [fd] [-1] [0] op string: [error] [Bad file descriptor] [0] op string: [test] [good] [0] op content: [fd] [-1] [0] op string: [error] [Bad fi] [0] op string: [test] [good] [0] op content: [lines] [20] [0] op content: [words] [30] [0] op content: [characters] [40] [0] op open_leaf_list: [bytes] [] [0] op content: [bytes] [0] [0x2004] op content: [bytes] [1] [0x2004] op content: [bytes] [2] [0x2004] op content: [bytes] [3] [0x2004] op content: [bytes] [4] [0x2004] op close_leaf_list: [bytes] [] [0] op content: [mbuf-current] [10] [0] op content: [mbuf-cache] [20] [0] op content: [mbuf-total] [30] [0] op content: [distance] [50] [0] op string: [location] [Boston] [0] op content: [memory] [64] [0] op content: [total] [640] [0] op content: [memory] [64] [0] op content: [total] [640] [0] op content: [ten] [10] [0] op content: [eleven] [11] [0] op content: [unknown] [1010] [0] op content: [unknown] [1010] [0] op content: [min] [15] [0x20] op content: [cur] [20] [0x20] -op content: [max] [30] [0] +op content: [max] [125] [0] op content: [min] [15] [0] op content: [cur] [20] [0] op content: [max] [125] [0] op content: [min] [15] [0x20] op content: [cur] [20] [0x20] op content: [max] [125] [0x20] op content: [min] [15] [0] op content: [cur] [20] [0] op content: [max] [125] [0] op content: [val1] [21] [0x8000] op content: [val2] [58368] [0x18000] op content: [val3] [100663296] [0x28000] op content: [val4] [44470272] [0x48000] op content: [val5] [1342172800] [0x28000] op open_list: [flag] [] [0] op string: [flag] [one] [0x2010] op string: [flag] [two] [0x2010] op string: [flag] [three] [0x2010] op close_list: [flag] [] [0] op content: [works] [null] [0x20] op content: [empty-tag] [true] [0x8] op string: [t1] [1000] [0x1010] op string: [t2] [test5000] [0x1010] op string: [t3] [ten-longx] [0x1010] op string: [t4] [xtest] [0x1010] op content: [count] [10] [0] op content: [test] [4] [0] op close_container: [data] [] [0] op close_container: [top] [] [0] op finish: [] [] [0] op flush: [] [] [0] Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.J.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.J.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.J.out (revision 322022) @@ -1,2 +1,2 @@ -{"top": {"data": {"what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":30,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":"this is an warning"}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}} +{"top": {"data": {"what":"braces","length":"abcdef","fd":-1,"error":"Bad file descriptor","test":"good","fd":-1,"error":"Bad fi","test":"good","lines":20,"words":30,"characters":40, "bytes": [0,1,2,3,4],"mbuf-current":10,"mbuf-cache":20,"mbuf-total":30,"distance":50,"location":"Boston","memory":64,"total":640,"memory":64,"total":640,"ten":10,"eleven":11,"unknown":1010,"unknown":1010,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"min":15,"cur":20,"max":125,"val1":21,"val2":58368,"val3":100663296,"val4":44470272,"val5":1342172800, "flag": ["one","two","three"],"works":null,"empty-tag":true,"t1":"1000","t2":"test5000","t3":"ten-longx","t4":"xtest", "__error": {"message":"this is an error"}, "__error": {"message":"two more errors"}, "__warning": {"message":"this is an warning"}, "__warning": {"message":"two more warnings"},"count":10,"test":4, "error": {"message":"Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n"}}} } Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.JP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.JP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.JP.out (revision 322022) @@ -1,82 +1,82 @@ { "top": { "data": { "what": "braces", "length": "abcdef", "fd": -1, "error": "Bad file descriptor", "test": "good", "fd": -1, "error": "Bad fi", "test": "good", "lines": 20, "words": 30, "characters": 40, "bytes": [ 0, 1, 2, 3, 4 ], "mbuf-current": 10, "mbuf-cache": 20, "mbuf-total": 30, "distance": 50, "location": "Boston", "memory": 64, "total": 640, "memory": 64, "total": 640, "ten": 10, "eleven": 11, "unknown": 1010, "unknown": 1010, "min": 15, "cur": 20, - "max": 30, + "max": 125, "min": 15, "cur": 20, "max": 125, "min": 15, "cur": 20, "max": 125, "min": 15, "cur": 20, "max": 125, "val1": 21, "val2": 58368, "val3": 100663296, "val4": 44470272, "val5": 1342172800, "flag": [ "one", "two", "three" ], "works": null, "empty-tag": true, "t1": "1000", "t2": "test5000", "t3": "ten-longx", "t4": "xtest", "__error": { "message": "this is an error" }, "__error": { "message": "two more errors" }, "__warning": { "message": "this is an warning" }, "__warning": { "message": "two more warnings" }, "count": 10, "test": 4, "error": { "message": "Shut 'er down, Clancey! She's a-pumpin' mud! <>!,\"!<>\n" } } } } Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.X.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.X.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.X.out (revision 322022) @@ -1,7 +1,7 @@ bracesabcdef abcdef: Bad file descriptor improper use of profanity; ten yard penalty; first down abcdef-1Bad file descriptorgood-1Bad figoodimproper use of profanity; ten yard penalty; first down -2030400123410203050Boston64640646401011101010101520301520125152012515201252158368100663296444702721342172800onetwothreenull1000test5000ten-longxxtest<__error>this is an error<__error>two more errors<__warning>this is an warning<__warning>two more warnings104improper use of profanity; ten yard penalty; first down +2030400123410203050Boston646406464010111010101015201251520125152012515201252158368100663296444702721342172800onetwothreenull1000test5000ten-longxxtest<__error>this is an error<__error>two more errors<__warning>this is an warning<__warning>two more warnings104improper use of profanity; ten yard penalty; first down Shut 'er down, Clancey! She's a-pumpin' mud! <>!,"!<> \ No newline at end of file Index: projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.XP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.XP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/saved/test_02.XP.out (revision 322022) @@ -1,87 +1,87 @@ braces abcdef abcdef: Bad file descriptor improper use of profanity; ten yard penalty; first down abcdef -1 Bad file descriptor good -1 Bad fi good improper use of profanity; ten yard penalty; first down 20 30 40 0 1 2 3 4 10 20 30 50 Boston 64 640 64 640 10 11 1010 1010 15 20 - 30 + 125 15 20 125 15 20 125 15 20 125 21 58368 100663296 44470272 1342172800 one two three null 1000 test5000 ten-longx xtest <__error> this is an error <__error> two more errors <__warning> this is an warning <__warning> two more warnings 10 4 improper use of profanity; ten yard penalty; first down Shut 'er down, Clancey! She's a-pumpin' mud! <>!,"!<> Index: projects/make-check-sandbox/contrib/libxo/tests/core/test_01.c =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/core/test_01.c (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/core/test_01.c (revision 322022) @@ -1,207 +1,211 @@ /* * Copyright (c) 2014, Juniper Networks, Inc. * All rights reserved. * This SOFTWARE is licensed under the LICENSE provided in the * ../Copyright file. By downloading, installing, copying, or otherwise * using the SOFTWARE, you agree to be bound by the terms of that * LICENSE. * Phil Shafer, July 2014 */ #include #include #include #include #include "xo.h" int main (int argc, char **argv) { static char base_grocery[] = "GRO"; static char base_hardware[] = "HRD"; struct item { const char *i_title; int i_sold; int i_instock; int i_onorder; const char *i_sku_base; int i_sku_num; }; struct item list[] = { { "gum", 1412, 54, 10, base_grocery, 415 }, { "rope", 85, 4, 2, base_hardware, 212 }, { "ladder", 0, 2, 1, base_hardware, 517 }, { "bolt", 4123, 144, 42, base_hardware, 632 }, { "water", 17, 14, 2, base_grocery, 2331 }, { NULL, 0, 0, 0, NULL, 0 } }; struct item list2[] = { { "fish", 1321, 45, 1, base_grocery, 533 }, { NULL, 0, 0, 0, NULL, 0 } }; struct item *ip; xo_info_t info[] = { { "in-stock", "number", "Number of items in stock" }, { "name", "string", "Name of the item" }, { "on-order", "number", "Number of items on order" }, { "sku", "string", "Stock Keeping Unit" }, { "sold", "number", "Number of items sold" }, { XO_INFO_NULL }, }; argc = xo_parse_args(argc, argv); if (argc < 0) return 1; for (argc = 1; argv[argc]; argc++) { if (strcmp(argv[argc], "xml") == 0) xo_set_style(NULL, XO_STYLE_XML); else if (strcmp(argv[argc], "json") == 0) xo_set_style(NULL, XO_STYLE_JSON); else if (strcmp(argv[argc], "text") == 0) xo_set_style(NULL, XO_STYLE_TEXT); else if (strcmp(argv[argc], "html") == 0) xo_set_style(NULL, XO_STYLE_HTML); else if (strcmp(argv[argc], "pretty") == 0) xo_set_flags(NULL, XOF_PRETTY); else if (strcmp(argv[argc], "xpath") == 0) xo_set_flags(NULL, XOF_XPATH); else if (strcmp(argv[argc], "info") == 0) xo_set_flags(NULL, XOF_INFO); else if (strcmp(argv[argc], "error") == 0) { close(-1); xo_err(1, "error detected"); } } xo_set_info(NULL, info, -1); xo_set_flags(NULL, XOF_KEYS); xo_open_container_h(NULL, "top"); + xo_emit("anchor {[:/%d}{:address/%p}..{:port/%u}{]:}\n", 18, NULL, 1); + xo_emit("anchor {[:18}{:address/%p}..{:port/%u}{]:}\n", NULL, 1); + xo_emit("anchor {[:/18}{:address/%p}..{:port/%u}{]:}\n", NULL, 1); + xo_emit("df {:used-percent/%5.0f}{U:%%}\n", (double) 12); xo_emit("{e:kve_start/%#jx}", (uintmax_t) 0xdeadbeef); xo_emit("{e:kve_end/%#jx}", (uintmax_t) 0xcabb1e); xo_emit("testing argument modifier {a:}.{a:}...\n", "host", "my-box", "domain", "example.com"); xo_emit("testing argument modifier with encoding to {ea:}.{a:}...\n", "host", "my-box", "domain", "example.com"); xo_emit("{La:} {a:}\n", "Label text", "label", "value"); xo_emit_field("Vt", "max-chaos", NULL, NULL, " very "); xo_emit_field("V", "min-chaos", "%d", NULL, 42); xo_emit_field("V", "some-chaos", "%d\n", "[%d]", 42); xo_emit("Connecting to {:host}.{:domain}...\n", "my-box", "example.com"); xo_attr("test", "value"); xo_open_container("data"); xo_open_list("item"); xo_attr("test2", "value2"); xo_emit("{T:Item/%-10s}{T:Total Sold/%12s}{T:In Stock/%12s}" "{T:On Order/%12s}{T:SKU/%5s}\n"); for (ip = list; ip->i_title; ip++) { xo_open_instance("item"); xo_attr("test3", "value3"); xo_emit("{keq:sku/%s-%u/%s-000-%u}" "{k:name/%-10s/%s}{n:sold/%12u/%u}{:in-stock/%12u/%u}" "{:on-order/%12u/%u}{qkd:sku/%5s-000-%u/%s-000-%u}\n", ip->i_sku_base, ip->i_sku_num, ip->i_title, ip->i_sold, ip->i_instock, ip->i_onorder, ip->i_sku_base, ip->i_sku_num); xo_close_instance("item"); } xo_close_list("item"); xo_close_container("data"); xo_emit("\n\n"); xo_open_container("data2"); xo_open_list("item"); for (ip = list; ip->i_title; ip++) { xo_open_instance("item"); xo_emit("{keq:sku/%s-%u/%s-000-%u}", ip->i_sku_base, ip->i_sku_num); xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title); xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n", ip->i_sold, ip->i_sold ? ".0" : ""); xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock); xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder); xo_emit("{P: }{L:SKU}: {qkd:sku/%s-000-%u}\n", ip->i_sku_base, ip->i_sku_num); xo_close_instance("item"); } xo_close_list("item"); xo_close_container("data2"); xo_open_container("data3"); xo_open_list("item"); for (ip = list2; ip->i_title; ip++) { xo_open_instance("item"); xo_emit("{keq:sku/%s-%u/%s-000-%u}", ip->i_sku_base, ip->i_sku_num); xo_emit("{L:Item} '{k:name/%s}':\n", ip->i_title); xo_emit("{P: }{L:Total sold}: {n:sold/%u%s}\n", ip->i_sold, ip->i_sold ? ".0" : ""); xo_emit("{P: }{Lcw:In stock}{:in-stock/%u}\n", ip->i_instock); xo_emit("{P: }{Lcw:On order}{:on-order/%u}\n", ip->i_onorder); xo_emit("{P: }{L:SKU}: {qkd:sku/%s-000-%u}\n", ip->i_sku_base, ip->i_sku_num); xo_close_instance("item"); } xo_close_list("item"); xo_close_container("data3"); xo_open_container("data4"); xo_open_list("item"); for (ip = list; ip->i_title; ip++) { xo_attr("test4", "value4"); xo_emit("{Lwc:Item}{l:item}\n", ip->i_title); } xo_close_list("item"); xo_close_container("data4"); xo_emit("X{P:}X", "epic fail"); xo_emit("X{T:}X", "epic fail"); xo_emit("X{N:}X", "epic fail"); xo_emit("X{L:}X\n", "epic fail"); xo_emit("X{P: }X{Lwc:Cost}{:cost/%u}\n", 425); xo_emit("X{P:/%30s}X{Lwc:Cost}{:cost/%u}\n", "", 455); xo_emit("{e:mode/%s}{e:mode_octal/%s} {t:links/%s} " "{t:user/%s} {t:group/%s} \n", "mode", "octal", "links", "user", "group", "extra1", "extra2", "extra3"); xo_emit("{e:pre/%s}{t:links/%-*u}{t:post/%-*s}\n", "that", 8, 3, 8, "this"); xo_emit("{t:mode/%s}{e:mode_octal/%03o} {t:links/%*u} " "{t:user/%-*s} {t:group/%-*s} \n", "/some/file", (int) 0640, 8, 1, 10, "user", 12, "group"); xo_close_container_h(NULL, "top"); xo_finish(); return 0; } Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.H.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.H.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.H.out (revision 322022) @@ -1 +1 @@ -
Item
one
is
number
001
,
color
:
red
Item
two
is
number
002
,
color
:
blue
Item
three
is
number
003
,
color
:
green
Item
four
is
number
004
,
color
:
yellow
\ No newline at end of file +
Item
one
is
number
001
,
color
:
red
Item
two
is
number
002
,
color
:
blue
Item
three
is
number
003
,
color
:
green
Item
four
is
number
004
,
color
:
yellow
0xdeadbeef
..
1
0xdeadbeef
..
1
0xdeadbeef
..
1
0xdeadbeef
..
1
\ No newline at end of file Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HIPx.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HIPx.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HIPx.out (revision 322022) @@ -1,52 +1,76 @@
Item
one
is
number
001
,
color
:
red
Item
two
is
number
002
,
color
:
blue
Item
three
is
number
003
,
color
:
green
Item
four
is
number
004
,
color
:
yellow
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.HP.out (revision 322022) @@ -1,52 +1,76 @@
Item
one
is
number
001
,
color
:
red
Item
two
is
number
002
,
color
:
blue
Item
three
is
number
003
,
color
:
green
Item
four
is
number
004
,
color
:
yellow
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
+
+
+
0xdeadbeef
+
..
+
1
+
Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.J.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.J.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.J.out (revision 322022) @@ -1 +1 @@ -"top": {"item": {"name":"one","value":1,"color":"red"}, "item": {"name":"two","value":2,"color":"blue"}, "item": {"name":"three","value":3,"color":"green"}, "item": {"name":"four","value":4,"color":"yellow"}} +"top": {"item": {"name":"one","value":1,"color":"red"}, "item": {"name":"two","value":2,"color":"blue"}, "item": {"name":"three","value":3,"color":"green"}, "item": {"name":"four","value":4,"color":"yellow"}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}, "anchor": {"address":"0xdeadbeef","foo":1}} Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.JP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.JP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.JP.out (revision 322022) @@ -1,22 +1,38 @@ "top": { "item": { "name": "one", "value": 1, "color": "red" }, "item": { "name": "two", "value": 2, "color": "blue" }, "item": { "name": "three", "value": 3, "color": "green" }, "item": { "name": "four", "value": 4, "color": "yellow" + }, + "anchor": { + "address": "0xdeadbeef", + "foo": 1 + }, + "anchor": { + "address": "0xdeadbeef", + "foo": 1 + }, + "anchor": { + "address": "0xdeadbeef", + "foo": 1 + }, + "anchor": { + "address": "0xdeadbeef", + "foo": 1 } } Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.T.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.T.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.T.out (revision 322022) @@ -1,4 +1,8 @@ Item one is number 001, color: red Item two is number 002, color: blue Item three is number 003, color: green Item four is number 004, color: yellow + 0xdeadbeef..1 + 0xdeadbeef..1 + 0xdeadbeef..1 + 0xdeadbeef..1 Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.X.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.X.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.X.out (revision 322022) @@ -1 +1 @@ -one1redtwo2bluethree3greenfour4yellow \ No newline at end of file +one1redtwo2bluethree3greenfour4yellow
0xdeadbeef
1
0xdeadbeef
1
0xdeadbeef
1
0xdeadbeef
1
\ No newline at end of file Index: projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.XP.out =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.XP.out (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/saved/xo_01.XP.out (revision 322022) @@ -1,22 +1,38 @@ one 1 red two 2 blue three 3 green four 4 yellow + +
0xdeadbeef
+ 1 +
+ +
0xdeadbeef
+ 1 +
+ +
0xdeadbeef
+ 1 +
+ +
0xdeadbeef
+ 1 +
Index: projects/make-check-sandbox/contrib/libxo/tests/xo/xo_01.sh =================================================================== --- projects/make-check-sandbox/contrib/libxo/tests/xo/xo_01.sh (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/tests/xo/xo_01.sh (revision 322022) @@ -1,27 +1,33 @@ # # $Id$ # # Copyright 2014, Juniper Networks, Inc. # All rights reserved. # This SOFTWARE is licensed under the LICENSE provided in the # ../Copyright file. By downloading, installing, copying, or otherwise # using the SOFTWARE, you agree to be bound by the terms of that # LICENSE. XO=$1 shift XOP="${XO} --warn --depth 1 --leading-xpath /top" ${XO} --open top NF= for i in one:1:red two:2:blue three:3:green four:4:yellow ; do set `echo $i | sed 's/:/ /g'` ${XOP} ${NF} --wrap item \ 'Item {k:name} is {Lw:number}{:value/%03d/%d}, {Lwc:color}{:color}\n' \ $1 $2 $3 NF=--not-first done -${XO} --close top \ No newline at end of file +XOAN="${XO} --wrap anchor --not-first --warn --depth 1" +${XOAN} "{[:18}{:address/%p}..{:foo/%u}{]:}\n" 0xdeadbeef 1 +${XOAN} "{[:/18}{:address/%p}..{:foo/%u}{]:}\n" 0xdeadbeef 1 +${XOAN} "{[:/%d}{:address/%p}..{:foo/%u}{]:}\n" 18 0xdeadbeef 1 +${XOAN} "{[:/%s}{:address/%p}..{:foo/%u}{]:}\n" 18 0xdeadbeef 1 + +${XO} --close top Index: projects/make-check-sandbox/contrib/libxo/xo/xo.1 =================================================================== --- projects/make-check-sandbox/contrib/libxo/xo/xo.1 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/xo/xo.1 (revision 322022) @@ -1,190 +1,200 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt XO 1 .Os .Sh NAME .Nm xo .Nd emit formatted output based on format string and arguments .Sh SYNOPSIS .Nm .Op Fl options .Op Ar argument... .Sh DESCRIPTION The .Nm utility allows command line access to the functionality of the .Nm libxo library. Using .Nm , shell scripts can emit .Em XML , .Em JSON , or .Em HTML using the same commands that emit text output. .Pp .Bl -tag -width indent .It Ic --close Ar path Close tags for the given path .It Ic --depth Ar num Set the depth for pretty printing .It Ic --help Display help text .It Ic -H | Ic --html Generate HTML output .It Ic -J | Ic --json Generate JSON output .It Ic --leading-xpath Ar path Add a prefix to generated XPaths (HTML) .It Ic --open Ar path Open tags for the given path .It Ic -p | Ic --pretty Make 'pretty' output (add indent, newlines) .It Ic --style Ar style Generate given style (xml, json, text, html) .It Ic -T | Ic --text Generate text output (the default style) .It Ic --version Display version information .It Ic -W | Ic --warn Display warnings in text on stderr .It Ic --warn-xml Display warnings in xml on stdout .It Ic --wrap Ar path Wrap output in a set of containers .It Ic -X | Ic --xml Generate XML output .It Ic --xpath Add XPath data to HTML output .El .Pp The .Nm utility accepts a format string suitable for .Xr xo_emit 3 and a set of zero or more arguments used to supply data for that string. .Pp In addition, .Nm accepts any of the .Nm libxo options listed in .Xr xo_options 7 . .Sh EXAMPLES In this example, .Nm is used to emit the same data encoded in text and then in XML by adding the "-p" (pretty) and "-X" (XML output) flags: .Bd -literal -offset indent % xo 'The {:product} is {:status}\\n' stereo "in route" The stereo is in route % xo -p -X 'The {:product} is {:status}\\n' stereo "in route" stereo in route .Ed .Pp In this example, the output from a .Nm command is shown in several styles: .Bd -literal -offset indent xo "The {k:name} weighs {:weight/%d} pounds.\\n" fish 6 .Pp TEXT: The fish weighs 6 pounds. XML: fish 6 JSON: "name": "fish", "weight": 6 HTML:
The
fish
weighs
6
pounds.
.Ed .Pp The .Fl "-wrap " option can be used to wrap emitted content in a specific hierarchy. The path is a set of hierarchical names separated by the '/' character. .Bd -literal -offset indent xo --wrap top/a/b/c '{:tag}' value .Pp XML: value JSON: "top": { "a": { "b": { "c": { "tag": "value" } } } } .Ed .Pp The .Fl "\-open " and .Fl "\-close " can be used to emit hierarchical information without the matching close and open tag. This allows a shell script to emit open tags, data, and then close tags. The .Fl \-depth option may be used to set the depth for indentation. The .Fl "\-leading-xpath" may be used to prepend data to the XPath values used for HTML output style. .Bd -literal -offset indent #!/bin/sh xo --open top/data xo --depth 2 '{tag}' value xo --close top/data .Pp XML: value JSON: "top": { "data": { "tag": "value" } } .Ed .Sh SEE ALSO .Xr libxo 3 , .Xr xo_emit 3 , .Xr xo_options 7 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.1 =================================================================== --- projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.1 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.1 (revision 322022) @@ -1,96 +1,103 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt XOHTML 1 .Os .Sh NAME .Nm xohtml .Nd display libxo html output .Xr xo_emit 3 .Sh SYNOPSIS .Nm xohtml .Op Fl "b " .Op Fl "c" " .Op Fl "f" -.Op Ar command argument... +.Op Fl "w" +.Op Ar command [argument ...] .Sh DESCRIPTION .Nm is a tool for preparing .Xr libxo 3 HTML output for display in modern HTML web browsers. .Nm can operate in two modes. If command is provided either with the .Fl c option or as argument(s) to the .Nm command, that command is executed and the resulting output is processed. If no command is given, the standard input is used. .Pp .Nm is typically used to wrap .Nm libxo output with sufficient HTML content to allow display in a web browser. This includes parent HTML tags as well as .Nm CSS stylesheets and .Nm Javascript files. .Pp If the command is given directly on the command line, .Nm will add the "--libxo=html" option needed to generate HTML output from .Nm libxo "-enabled" applications. See .Xr xo_options 7 for details. .Pp The following options are available: .Bl -tag -width indent .It Ic -b Ar base | Ic --base Ar base Supplies a source path for the CSS and Javascript files referenced in the output of .Nm xohtml . .It Ic -c Ar command | Ic --command Ar command Use the given command instead of one on the command line. This command should be quoted if it consists of multiple tokens, and should contain the "--libxo=html" option or equivalent, since the command is used directly. .It Ic -f Ar file | Ic --file Ar file Output is saved to the given file, rather than to the standard output descriptor. +.It Ic -w | --web +Uses the official +.Nm libxo +website URL as the source path for the CSS and Javascript files +referenced in the output of +.Nm xohtml . .El .Pp .Sh EXAMPLES The following command line will run "du --libxo=html ~/src" and save the output to /tmp/src.html: .Bd -literal -offset indent xohtml du ~/src > /tmp/src.html .Ed .Pp The following command line will run "du --libxo=html,warn ~/src" and save the output to /tmp/src.html: .Bd -literal -offset indent du --libxo=html,warn ~/src | xohtml -f /tmp/src.html .Ed .Pp The following command line will run "du --libxo=html,warn ~/src" and save the output to /tmp/src.html: .Bd -literal -offset indent xohtml -c "du --libxo=html,warn ~/src" -f /tmp/src.html .Ed .Pp .Sh SEE ALSO .Xr libxo 3 , .Xr xo_emit 3 , .Xr xo_options 7 Index: projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.sh.in =================================================================== --- projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.sh.in (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/xohtml/xohtml.sh.in (revision 322022) @@ -1,78 +1,85 @@ #!/bin/sh # # Copyright (c) 2014, Juniper Networks, Inc. # All rights reserved. # This SOFTWARE is licensed under the LICENSE provided in the # ../Copyright file. By downloading, installing, copying, or otherwise # using the SOFTWARE, you agree to be bound by the terms of that # LICENSE. # Phil Shafer, July 2014 # BASE=@XO_SHAREDIR@ +VERSION=@LIBXO_VERSION@ CMD=cat DONE= +WEB=http://juniper.github.io/libxo/${VERSION}/xohtml do_help () { echo "xohtml: wrap libxo-enabled output in HTML" echo "Usage: xohtml [options] [command [arguments]]" echo "Valid options are:" echo " -b | --base " echo " -c | --command " echo " -f | --file " exit 1 } while [ -z "$DONE" -a ! -z "$1" ]; do case "$1" in -b|--base) shift; BASE="$1"; shift; ;; -c|--command) shift; CMD="$1"; shift; ;; -f|--file) shift; FILE="$1"; shift; exec > "$FILE"; ;; + -w|--web) + shift; + BASE="${WEB}"; + ;; + -*) do_help ;; *) DONE=1; XX=$1; shift; CMD="$XX --libxo=html $@" ;; esac done if [ "$CMD" = "cat" -a -t 0 ]; then do_help fi echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' $CMD echo '' echo '' exit 0 Index: projects/make-check-sandbox/contrib/libxo/xolint/xolint.1 =================================================================== --- projects/make-check-sandbox/contrib/libxo/xolint/xolint.1 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/xolint/xolint.1 (revision 322022) @@ -1,79 +1,89 @@ .\" # .\" # Copyright (c) 2014, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2014 .\" .Dd December 4, 2014 .Dt XOLINT 1 .Os .Sh NAME .Nm xolint .Nd detect errors in programs using .Xr xo_emit 3 .Sh SYNOPSIS .Nm xolint .Op Fl c .Op Fl "C " .Op Fl "d" .Op Fl "D" .Op Fl "I" .Op Fl "p" .Op Fl "V" .Op Fl "X" .Op Ar files... .Sh DESCRIPTION .Nm is a tool for reporting common mistakes in format strings in source code that invokes .Xr xo_emit 3 . It allows these errors to be diagnosed at build time, rather than waiting until runtime. .Pp .Nm takes one or more C files as arguments, and reports error, warning, or informational messages as needed. .Bl -tag -width "C " .It Fl c Invoke 'cpp' against the input file .It Fl "C " Flags that are passed to 'cpp' .It Fl "d" Enable debug output .It Fl "D" Generate documentation for all .Nm messages .It Fl "I" Generate a table of .Dv xo_info_t structures. .It Fl "p" Print the offending lines after the error message is displayed .It Fl "V" Do not report errors, but instead print a complete list of all field names, sorted alphabetically. The output can help spot inconsistencies and spelling errors. .It Fl "X" Extract samples from .Nm , suitable for internal testing. .El .Pp The output message contains the source filename and line number, the class of the message, the message, and, if .Fl p is given, the line that contains the error: .Bd -literal -offset indent % xolint -t xolint.c xolint.c: 16: error: anchor format should be "%d" 16 xo_emit("{[:/%s}"); .Ed .Sh SEE ALSO .Xr libxo 3 , .Xr xo_emit 3 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo/xopo/xopo.1 =================================================================== --- projects/make-check-sandbox/contrib/libxo/xopo/xopo.1 (revision 322021) +++ projects/make-check-sandbox/contrib/libxo/xopo/xopo.1 (revision 322022) @@ -1,77 +1,87 @@ .\" # .\" # Copyright (c) 2015, Juniper Networks, Inc. .\" # All rights reserved. .\" # This SOFTWARE is licensed under the LICENSE provided in the .\" # ../Copyright file. By downloading, installing, copying, or .\" # using the SOFTWARE, you agree to be bound by the terms of that .\" # LICENSE. .\" # Phil Shafer, July 2015 .\" .Dd July 9, 2015 .Dt XOPO 1 .Os .Sh NAME .Nm xopo .Nd turn libxo format strings into simplified form .Sh SYNOPSIS .Nm .Op Fl options .Sh DESCRIPTION The .Nm utility simplifies libxo format strings into the form used for .Xr gettext lookups by the .Nm libxo library. Using .Nm , users can turn .Em .pot files generated by .Xr xgettext into data useful for libxo-enabled applications. .Pp Since .Xr gettext uses the string as the key into the message catalog, .Nm libxo uses a simplified version of the format string that removes unimportant field formatting and modifiers, stopping minor formatting changes from impacting the expensive translation process. A developer change such as changing "/%06d" to "/%08d" should not force hand inspection of all .po files. .Pp .Nm inspects the input file, looking for lines that begin with "msgid" which carry format strings as the remainder of the input line. These strings are passed to .Nm libxo for simplification and the resulting strings are replaced into the output stream, allowing .Nm to operated as a filter. .Pp .Bl -tag -width indent .It Ic -f Ar pofile | Ic --po Ar pofile Use the given po file for input. .It Ic --help Display this help text .It Ic -o Ar file | Ic --output Ar file Write output content to the given file .It Ic -s Ar text | Ic --simplify Ar text Generate the simplified version of a single text string. .It Ic -W | Ic --warn Generate warnings while parsing the format strings .It Ic --version Display version information .El .Pp .Sh EXAMPLE .Bd -literal % xopo -f foo.pot -o foo.pot.new .Ed .Sh SEE ALSO .Xr libxo 3 , .Xr xo_format 5 +.Sh HISTORY +The +.Nm libxo +library first appeared in +.Fx 11.0 . +.Sh AUTHORS +.Nm libxo +was written by +.An Phil Shafer Aq Mt phil@freebsd.org . + Index: projects/make-check-sandbox/contrib/libxo =================================================================== --- projects/make-check-sandbox/contrib/libxo (revision 322021) +++ projects/make-check-sandbox/contrib/libxo (revision 322022) Property changes on: projects/make-check-sandbox/contrib/libxo ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,2 ## Merged /vendor/Juniper/libxo/dist:r319999-322018 Merged /head/contrib/libxo:r321438-322021 Index: projects/make-check-sandbox/lib/libxo/add.man =================================================================== --- projects/make-check-sandbox/lib/libxo/add.man (revision 322021) +++ projects/make-check-sandbox/lib/libxo/add.man (revision 322022) @@ -1,30 +1,30 @@ .\" $FreeBSD$ .Sh ADDITIONAL DOCUMENTATION .Fx uses .Nm libxo -version 0.8.1. +version 0.8.4. Complete documentation can be found on github: .Bd -literal -offset indent -http://juniper.github.io/libxo/0.8.1/libxo\-manual.html +http://juniper.github.io/libxo/0.8.4/libxo\-manual.html .Ed .Pp .Nm libxo lives on github as: .Bd -literal -offset indent https://github.com/Juniper/libxo .Ed .Pp The latest release of .Nm libxo is available at: .Bd -literal -offset indent https://github.com/Juniper/libxo/releases .Ed .Sh HISTORY The .Nm libxo library was added in .Fx 11.0 . .Sh AUTHOR Phil Shafer Index: projects/make-check-sandbox/lib/libxo/xo_config.h =================================================================== --- projects/make-check-sandbox/lib/libxo/xo_config.h (revision 322021) +++ projects/make-check-sandbox/lib/libxo/xo_config.h (revision 322022) @@ -1,257 +1,257 @@ /* $FreeBSD$ */ /* libxo/xo_config.h. Generated from xo_config.h.in by configure. */ /* libxo/xo_config.h.in. Generated from configure.ac by autoheader. */ /* Define to one of `_getb67', `GETB67', `getb67' for Cray-2 and Cray-YMP systems. This function is required for `alloca.c' support on those systems. */ /* #undef CRAY_STACKSEG_END */ /* Define to 1 if using `alloca.c'. */ /* #undef C_ALLOCA */ /* Define to 1 if you have `alloca', as a function or macro. */ #define HAVE_ALLOCA 1 /* Define to 1 if you have and it should be used (not on Ultrix). */ /* #undef HAVE_ALLOCA_H */ /* Define to 1 if you have the `asprintf' function. */ #define HAVE_ASPRINTF 1 /* Define to 1 if you have the `bzero' function. */ #define HAVE_BZERO 1 /* Define to 1 if you have the `ctime' function. */ #define HAVE_CTIME 1 /* Define to 1 if you have the header file. */ #define HAVE_CTYPE_H 1 /* Define to 1 if you have the declaration of `__isthreaded', and to 0 if you don't. */ #define HAVE_DECL___ISTHREADED 1 /* Define to 1 if you have the header file. */ #define HAVE_DLFCN_H 1 /* Define to 1 if you have the `dlfunc' function. */ #define HAVE_DLFUNC 1 /* Define to 1 if you have the header file. */ #define HAVE_ERRNO_H 1 /* Define to 1 if you have the `fdopen' function. */ #define HAVE_FDOPEN 1 /* Define to 1 if you have the `flock' function. */ #define HAVE_FLOCK 1 /* Define to 1 if you have the `getpass' function. */ #define HAVE_GETPASS 1 /* Define to 1 if you have the `getprogname' function. */ #define HAVE_GETPROGNAME 1 /* Define to 1 if you have the `getrusage' function. */ #define HAVE_GETRUSAGE 1 /* gettext(3) */ /* #undef HAVE_GETTEXT */ /* Define to 1 if you have the `gettimeofday' function. */ #define HAVE_GETTIMEOFDAY 1 /* humanize_number(3) */ #define HAVE_HUMANIZE_NUMBER 1 /* Define to 1 if you have the header file. */ #define HAVE_INTTYPES_H 1 /* Define to 1 if you have the `crypto' library (-lcrypto). */ #define HAVE_LIBCRYPTO 1 /* Define to 1 if you have the `m' library (-lm). */ #define HAVE_LIBM 1 /* Define to 1 if you have the header file. */ #define HAVE_LIBUTIL_H 1 /* Define to 1 if your system has a GNU libc compatible `malloc' function, and to 0 otherwise. */ #define HAVE_MALLOC 1 /* Define to 1 if you have the `memmove' function. */ #define HAVE_MEMMOVE 1 /* Define to 1 if you have the header file. */ #define HAVE_MEMORY_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_MONITOR_H */ /* Support printflike */ /* #undef HAVE_PRINTFLIKE */ /* Define to 1 if your system has a GNU libc compatible `realloc' function, and to 0 otherwise. */ #define HAVE_REALLOC 1 /* Define to 1 if you have the `srand' function. */ #define HAVE_SRAND 1 /* Define to 1 if you have the `sranddev' function. */ #define HAVE_SRANDDEV 1 /* Define to 1 if you have the header file. */ #define HAVE_STDINT_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_STDIO_EXT_H */ /* Define to 1 if you have the header file. */ #define HAVE_STDIO_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STDLIB_H 1 /* Define to 1 if you have the header file. */ /* #undef HAVE_STDTIME_TZFILE_H */ /* Define to 1 if you have the `strchr' function. */ #define HAVE_STRCHR 1 /* Define to 1 if you have the `strcspn' function. */ #define HAVE_STRCSPN 1 /* Define to 1 if you have the `strerror' function. */ #define HAVE_STRERROR 1 /* Define to 1 if you have the header file. */ #define HAVE_STRINGS_H 1 /* Define to 1 if you have the header file. */ #define HAVE_STRING_H 1 /* Define to 1 if you have the `strlcpy' function. */ #define HAVE_STRLCPY 1 /* Define to 1 if you have the `strspn' function. */ #define HAVE_STRSPN 1 /* Have struct sockaddr_un.sun_len */ #define HAVE_SUN_LEN 1 /* Define to 1 if you have the `sysctlbyname' function. */ #define HAVE_SYSCTLBYNAME 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_PARAM_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_STAT_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_SYSCTL_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TIME_H 1 /* Define to 1 if you have the header file. */ #define HAVE_SYS_TYPES_H 1 /* Define to 1 if you have the header file. */ #define HAVE_THREADS_H 1 /* thread-local setting */ #define HAVE_THREAD_LOCAL THREAD_LOCAL_before /* Define to 1 if you have the header file. */ /* #undef HAVE_TZFILE_H */ /* Define to 1 if you have the header file. */ #define HAVE_UNISTD_H 1 /* Define to 1 if you have the `__flbf' function. */ /* #undef HAVE___FLBF */ /* Enable debugging */ /* #undef LIBXO_DEBUG */ /* Enable text-only rendering */ /* #undef LIBXO_TEXT_ONLY */ /* Version number as dotted value */ -#define LIBXO_VERSION "0.8.1" +#define LIBXO_VERSION "0.8.4" /* Version number extra information */ #define LIBXO_VERSION_EXTRA "" /* Version number as a number */ -#define LIBXO_VERSION_NUMBER 8001 +#define LIBXO_VERSION_NUMBER 8004 /* Version number as string */ -#define LIBXO_VERSION_STRING "8001" +#define LIBXO_VERSION_STRING "8004" /* Enable local wcwidth implementation */ #define LIBXO_WCWIDTH 1 /* Define to the sub-directory where libtool stores uninstalled libraries. */ #define LT_OBJDIR ".libs/" /* Name of package */ #define PACKAGE "libxo" /* Define to the address where bug reports for this package should be sent. */ #define PACKAGE_BUGREPORT "phil@juniper.net" /* Define to the full name of this package. */ #define PACKAGE_NAME "libxo" /* Define to the full name and version of this package. */ -#define PACKAGE_STRING "libxo 0.8.1" +#define PACKAGE_STRING "libxo 0.8.4" /* Define to the one symbol short name of this package. */ #define PACKAGE_TARNAME "libxo" /* Define to the home page for this package. */ #define PACKAGE_URL "" /* Define to the version of this package. */ -#define PACKAGE_VERSION "0.8.1" +#define PACKAGE_VERSION "0.8.4" /* If using the C implementation of alloca, define if you know the direction of stack growth for your system; otherwise it will be automatically deduced at runtime. STACK_DIRECTION > 0 => grows toward higher addresses STACK_DIRECTION < 0 => grows toward lower addresses STACK_DIRECTION = 0 => direction of growth unknown */ /* #undef STACK_DIRECTION */ /* Define to 1 if you have the ANSI C header files. */ #define STDC_HEADERS 1 /* Use int return codes */ /* #undef USE_INT_RETURN_CODES */ /* Version number of package */ -#define VERSION "0.8.1" +#define VERSION "0.8.4" /* Retain hash bucket size */ /* #undef XO_RETAIN_SIZE */ /* Define to `__inline__' or `__inline' if that's what the C compiler calls it, or to nothing if 'inline' is not supported under any name. */ #ifndef __cplusplus /* #undef inline */ #endif /* Define to rpl_malloc if the replacement function should be used. */ /* #undef malloc */ /* Define to rpl_realloc if the replacement function should be used. */ /* #undef realloc */ /* Define to `unsigned int' if does not define. */ /* #undef size_t */ Index: projects/make-check-sandbox/sys/arm/conf/IMX6 =================================================================== --- projects/make-check-sandbox/sys/arm/conf/IMX6 (revision 322021) +++ projects/make-check-sandbox/sys/arm/conf/IMX6 (revision 322022) @@ -1,125 +1,128 @@ # # Kernel configuration for Freescale i.MX6 systems. # # For more information on this file, please read the config(5) manual page, # and/or the handbook section on Kernel Configuration Files: # # http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html # # The handbook is also available locally in /usr/share/doc/handbook # if you've installed the doc distribution, otherwise always see the # FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the # latest information. # # An exhaustive list of options and more detailed explanations of the # device lines is also present in the ../../conf/NOTES and NOTES files. # If you are in doubt as to the purpose or necessity of a line, check first # in NOTES. # # $FreeBSD$ ident IMX6 include "std.armv6" include "../freescale/imx/std.imx6" options INTRNG options SOC_IMX6 options SCHED_ULE # ULE scheduler #options NFSD # Network Filesystem Server options INCLUDE_CONFIG_FILE # Include this file in kernel options PLATFORM options SMP # Enable multiple cores # NFS root from boopt/dhcp #options BOOTP #options BOOTP_NFSROOT #options BOOTP_COMPAT #options BOOTP_NFSV3 #options BOOTP_WIRED_TO=ffec0 # U-Boot stuff lives on slice 1, FreeBSD on slice 2. options ROOTDEVNAME=\"ufs:mmcsd0s2a\" # Interrupt controller device gic # Cache controller device pl310 # PL310 L2 cache controller # ARM MPCore timer device mpcore_timer # Pseudo devices. device loop # Network loopback device random # Entropy device device vlan # 802.1Q VLAN support device tun # Packet tunnel. device md # Memory "disks" #device gif # IPv6 and IPv4 tunneling #device firmware # firmware assist module device ether # Ethernet support device miibus # Required for ethernet device bpf # Berkeley packet filter (required for DHCP) # General-purpose input/output device gpio # Serial (COM) ports device uart # Multi-uart driver # SDCard device sdhci # SD controller device mmc # SD/MMC protocol device mmcsd # SDCard disk device # SCSI peripherals device scbus # SCSI bus (required for ATA/SCSI) device da # Direct Access (disks) device cd # CD device pass # Passthrough device (direct ATA/SCSI access) +# ATA controllers +device ahci # AHCI-compatible SATA controllers + # USB support device ehci # OHCI USB interface device usb # USB Bus (required) device umass # Disks/Mass storage - Requires scbus and da device uhid # "Human Interface Devices" device u3g # USB modems #device ukbd # Allow keyboard like HIDs to control console #device ums # USB mouse # USB Ethernet, requires miibus #device aue # ADMtek USB Ethernet #device axe # ASIX Electronics USB Ethernet #device cdce # Generic USB over Ethernet #device cue # CATC USB Ethernet #device kue # Kawasaki LSI USB Ethernet #device rue # RealTek RTL8150 USB Ethernet #device udav # Davicom DM9601E USB # USB Wireless #device rum # Ralink Technology RT2501USB wireless NICs # Wireless NIC cards #device wlan # 802.11 support #device wlan_wep # 802.11 WEP support #device wlan_ccmp # 802.11 CCMP support #device wlan_tkip # 802.11 TKIP support #device wlan_amrr # AMRR transmit rate control algorithm device vt device kbdmux device ukbd device videomode device hdmi # Flattened Device Tree options FDT # Configure using FDT/DTB data makeoptions MODULES_EXTRA=dtb/imx6 # SoC-specific devices device ffec # Freescale Fast Ethernet Controller device fsliic # Freescale i2c/iic device iic # iic protocol device iicbus # iic bus device imxwdt # Watchdog. WARNING: can't be disabled!!! Index: projects/make-check-sandbox/sys/arm/freescale/imx/files.imx6 =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/files.imx6 (revision 322021) +++ projects/make-check-sandbox/sys/arm/freescale/imx/files.imx6 (revision 322022) @@ -1,73 +1,74 @@ # $FreeBSD$ # # Standard ARM support. # kern/kern_clocksource.c standard # # Standard imx6 devices and support. # arm/freescale/fsl_ocotp.c standard arm/freescale/imx/imx6_anatop.c standard arm/freescale/imx/imx6_ccm.c standard arm/freescale/imx/imx6_machdep.c standard arm/freescale/imx/imx6_mp.c optional smp arm/freescale/imx/imx6_pl310.c standard arm/freescale/imx/imx6_snvs.c optional imx6_snvs arm/freescale/imx/imx6_src.c standard arm/freescale/imx/imx_epit.c standard arm/freescale/imx/imx_iomux.c standard arm/freescale/imx/imx_machdep.c standard arm/freescale/imx/imx_gpt.c optional imx_gpt arm/freescale/imx/imx_gpio.c optional gpio arm/freescale/imx/imx_i2c.c optional fsliic arm/freescale/imx/imx6_sdma.c optional sdma arm/freescale/imx/imx6_audmux.c optional sound arm/freescale/imx/imx6_ssi.c optional sound +arm/freescale/imx/imx6_ahci.c optional ahci dev/hdmi/hdmi_if.m optional hdmi dev/hdmi/dwc_hdmi.c optional hdmi arm/freescale/imx/imx6_hdmi.c optional hdmi arm/freescale/imx/imx6_ipu.c optional vt # # Optional devices. # dev/sdhci/fsl_sdhci.c optional sdhci arm/freescale/imx/imx_wdog.c optional imxwdt dev/ffec/if_ffec.c optional ffec dev/uart/uart_dev_imx.c optional uart dev/usb/controller/ehci_imx.c optional ehci arm/freescale/imx/imx6_usbphy.c optional ehci # # Low-level serial console for debugging early kernel startup. # #arm/freescale/imx/imx_console.c standard # # Not ready yet... # #arm/freescale/imx/imx51_ipuv3.c optional sc # SDMA firmware sdma_fw.c optional sdma_fw \ compile-with "${AWK} -f $S/tools/fw_stub.awk sdma-imx6q-to1.bin:sdma_fw -msdma -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "sdma_fw.c" sdma-imx6q-to1.fwo optional sdma_fw \ dependency "sdma-imx6q-to1.bin" \ compile-with "${LD} -b binary -d -warn-common -r -d -o ${.TARGET} sdma-imx6q-to1.bin" \ no-implicit-rule \ clean "sdma-imx6q-to1.fwo" sdma-imx6q-to1.bin optional sdma_fw \ dependency "$S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \ compile-with "uudecode < $S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \ no-obj no-implicit-rule \ clean "sdma-imx6q-to1.bin" Index: projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ahci.c =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ahci.c (nonexistent) +++ projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ahci.c (revision 322022) @@ -0,0 +1,358 @@ +/*- + * Copyright (c) 2017 Rogiel Sulzbach + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include + +__FBSDID("$FreeBSD$"); + +#include +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include +#include +#include + +#define SATA_TIMER1MS 0x000000e0 + +#define SATA_P0PHYCR 0x00000178 +#define SATA_P0PHYCR_CR_READ (1 << 19) +#define SATA_P0PHYCR_CR_WRITE (1 << 18) +#define SATA_P0PHYCR_CR_CAP_DATA (1 << 17) +#define SATA_P0PHYCR_CR_CAP_ADDR (1 << 16) +#define SATA_P0PHYCR_CR_DATA_IN(v) ((v) & 0xffff) + +#define SATA_P0PHYSR 0x0000017c +#define SATA_P0PHYSR_CR_ACK (1 << 18) +#define SATA_P0PHYSR_CR_DATA_OUT(v) ((v) & 0xffff) + +/* phy registers */ +#define SATA_PHY_CLOCK_RESET 0x7f3f +#define SATA_PHY_CLOCK_RESET_RST (1 << 0) + +#define SATA_PHY_LANE0_OUT_STAT 0x2003 +#define SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE (1 << 1) + +static int +imx6_ahci_phy_ctrl(struct ahci_controller* sc, uint32_t bitmask, bool on) +{ + uint32_t v; + int timeout; + bool state; + + v = ATA_INL(sc->r_mem, SATA_P0PHYCR); + if (on) { + v |= bitmask; + } else { + v &= ~bitmask; + } + ATA_OUTL(sc->r_mem, SATA_P0PHYCR, v); + + for (timeout = 5000; timeout > 0; --timeout) { + v = ATA_INL(sc->r_mem, SATA_P0PHYSR); + state = (v & SATA_P0PHYSR_CR_ACK) == SATA_P0PHYSR_CR_ACK; + if(state == on) { + break; + } + DELAY(100); + } + + if (timeout > 0) { + return (0); + } + + return (ETIMEDOUT); +} + +static int +imx6_ahci_phy_addr(struct ahci_controller* sc, uint32_t addr) +{ + int error; + + DELAY(100); + + ATA_OUTL(sc->r_mem, SATA_P0PHYCR, addr); + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, true); + if (error != 0) { + device_printf(sc->dev, + "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=1\n", + __FUNCTION__); + return (error); + } + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_ADDR, false); + if (error != 0) { + device_printf(sc->dev, + "%s: timeout on SATA_P0PHYCR_CR_CAP_ADDR=0\n", + __FUNCTION__); + return (error); + } + + return (0); +} + +static int +imx6_ahci_phy_write(struct ahci_controller* sc, uint32_t addr, + uint16_t data) +{ + int error; + + error = imx6_ahci_phy_addr(sc, addr); + if (error != 0) { + device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", + __FUNCTION__); + return (error); + } + + ATA_OUTL(sc->r_mem, SATA_P0PHYCR, data); + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, true); + if (error != 0) { + device_printf(sc->dev, + "%s: error on SATA_P0PHYCR_CR_CAP_DATA=1\n", __FUNCTION__); + return (error); + } + if (imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_CAP_DATA, false) != 0) { + device_printf(sc->dev, + "%s: error on SATA_P0PHYCR_CR_CAP_DATA=0\n", __FUNCTION__); + return (error); + } + + if ((addr == SATA_PHY_CLOCK_RESET) && data) { + /* we can't check ACK after RESET */ + ATA_OUTL(sc->r_mem, SATA_P0PHYCR, + SATA_P0PHYCR_CR_DATA_IN(data) | SATA_P0PHYCR_CR_WRITE); + return (0); + } + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, true); + if (error != 0) { + device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=1\n", + __FUNCTION__); + return (error); + } + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_WRITE, false); + if (error != 0) { + device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_WRITE=0\n", + __FUNCTION__); + return (error); + } + + return (0); +} + +static int +imx6_ahci_phy_read(struct ahci_controller* sc, uint32_t addr, uint16_t* val) +{ + int error; + uint32_t v; + + error = imx6_ahci_phy_addr(sc, addr); + if (error != 0) { + device_printf(sc->dev, "%s: error on imx6_ahci_phy_addr\n", + __FUNCTION__); + return (error); + } + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, true); + if (error != 0) { + device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=1\n", + __FUNCTION__); + return (error); + } + + v = ATA_INL(sc->r_mem, SATA_P0PHYSR); + + error = imx6_ahci_phy_ctrl(sc, SATA_P0PHYCR_CR_READ, false); + if (error != 0) { + device_printf(sc->dev, "%s: error on SATA_P0PHYCR_CR_READ=0\n", + __FUNCTION__); + return (error); + } + + *val = SATA_P0PHYSR_CR_DATA_OUT(v); + return (0); +} + +static int +imx6_ahci_probe(device_t dev) +{ + + if (!ofw_bus_status_okay(dev)) { + return (ENXIO); + } + + if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ahci")) { + return (ENXIO); + } + device_set_desc(dev, "i.MX6 Integrated AHCI controller"); + + return (BUS_PROBE_DEFAULT); +} + +static int +imx6_ahci_attach(device_t dev) +{ + struct ahci_controller* ctlr; + uint16_t pllstat; + uint32_t v; + int error, timeout; + + ctlr = device_get_softc(dev); + + /* Power up the controller and phy. */ + error = imx6_ccm_sata_enable(); + if (error != 0) { + device_printf(dev, "error enabling controller and phy\n"); + return (error); + } + + ctlr->vendorid = 0; + ctlr->deviceid = 0; + ctlr->subvendorid = 0; + ctlr->subdeviceid = 0; + ctlr->numirqs = 1; + ctlr->r_rid = 0; + if ((ctlr->r_mem = bus_alloc_resource_any(dev, SYS_RES_MEMORY, + &ctlr->r_rid, RF_ACTIVE)) == NULL) { + return (ENXIO); + } + + v = imx_iomux_gpr_get(IOMUX_GPR13); + /* Clear out existing values; these numbers are bitmasks. */ + v &= ~(IOMUX_GPR13_SATA_PHY_8(7) | + IOMUX_GPR13_SATA_PHY_7(0x1f) | + IOMUX_GPR13_SATA_PHY_6(7) | + IOMUX_GPR13_SATA_SPEED(1) | + IOMUX_GPR13_SATA_PHY_5(1) | + IOMUX_GPR13_SATA_PHY_4(7) | + IOMUX_GPR13_SATA_PHY_3(0xf) | + IOMUX_GPR13_SATA_PHY_2(0x1f) | + IOMUX_GPR13_SATA_PHY_1(1) | + IOMUX_GPR13_SATA_PHY_0(1)); + /* setting */ + v |= IOMUX_GPR13_SATA_PHY_8(5) | /* Rx 3.0db */ + IOMUX_GPR13_SATA_PHY_7(0x12) | /* Rx SATA2m */ + IOMUX_GPR13_SATA_PHY_6(3) | /* Rx DPLL mode */ + IOMUX_GPR13_SATA_SPEED(1) | /* 3.0GHz */ + IOMUX_GPR13_SATA_PHY_5(0) | /* SpreadSpectram */ + IOMUX_GPR13_SATA_PHY_4(4) | /* Tx Attenuation 9/16 */ + IOMUX_GPR13_SATA_PHY_3(0) | /* Tx Boost 0db */ + IOMUX_GPR13_SATA_PHY_2(0x11) | /* Tx Level 1.104V */ + IOMUX_GPR13_SATA_PHY_1(1); /* PLL clock enable */ + imx_iomux_gpr_set(IOMUX_GPR13, v); + + /* phy reset */ + error = imx6_ahci_phy_write(ctlr, SATA_PHY_CLOCK_RESET, + SATA_PHY_CLOCK_RESET_RST); + if (error != 0) { + device_printf(dev, "cannot reset PHY\n"); + goto fail; + } + + for (timeout = 50; timeout > 0; --timeout) { + DELAY(100); + error = imx6_ahci_phy_read(ctlr, SATA_PHY_LANE0_OUT_STAT, + &pllstat); + if (error != 0) { + device_printf(dev, "cannot read LANE0 status\n"); + goto fail; + } + if (pllstat & SATA_PHY_LANE0_OUT_STAT_RX_PLL_STATE) { + break; + } + } + if (timeout <= 0) { + device_printf(dev, "time out reading LANE0 status\n"); + error = ETIMEDOUT; + goto fail; + } + + /* Support Staggered Spin-up */ + v = ATA_INL(ctlr->r_mem, AHCI_CAP); + ATA_OUTL(ctlr->r_mem, AHCI_CAP, v | AHCI_CAP_SSS); + + /* Ports Implemented. must set 1 */ + v = ATA_INL(ctlr->r_mem, AHCI_PI); + ATA_OUTL(ctlr->r_mem, AHCI_PI, v | (1 << 0)); + + /* set 1ms-timer = AHB clock / 1000 */ + ATA_OUTL(ctlr->r_mem, SATA_TIMER1MS, + imx_ccm_ahb_hz() / 1000); + + /* + * Note: ahci_attach will release ctlr->r_mem on errors automatically + */ + return (ahci_attach(dev)); + +fail: + bus_release_resource(dev, SYS_RES_MEMORY, ctlr->r_rid, ctlr->r_mem); + return (error); +} + +static int +imx6_ahci_detach(device_t dev) +{ + + return (ahci_detach(dev)); +} + +devclass_t ahci_devclass; + +static device_method_t imx6_ahci_ata_methods[] = { + /* device probe, attach and detach methods */ + DEVMETHOD(device_probe, imx6_ahci_probe), + DEVMETHOD(device_attach, imx6_ahci_attach), + DEVMETHOD(device_detach, imx6_ahci_detach), + + /* ahci bus methods */ + DEVMETHOD(bus_print_child, ahci_print_child), + DEVMETHOD(bus_alloc_resource, ahci_alloc_resource), + DEVMETHOD(bus_release_resource, ahci_release_resource), + DEVMETHOD(bus_setup_intr, ahci_setup_intr), + DEVMETHOD(bus_teardown_intr, ahci_teardown_intr), + DEVMETHOD(bus_child_location_str, ahci_child_location_str), + + DEVMETHOD_END +}; + +static driver_t ahci_ata_driver = { + "ahci", + imx6_ahci_ata_methods, + sizeof(struct ahci_controller) +}; + +DRIVER_MODULE(ahci, simplebus, ahci_ata_driver, ahci_devclass, 0, 0); Property changes on: projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ahci.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccm.c =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccm.c (revision 322021) +++ projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccm.c (revision 322022) @@ -1,421 +1,456 @@ /*- * Copyright (c) 2013 Ian Lepore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); /* * Clocks and power control driver for Freescale i.MX6 family of SoCs. */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifndef CCGR_CLK_MODE_ALWAYS #define CCGR_CLK_MODE_OFF 0 #define CCGR_CLK_MODE_RUNMODE 1 #define CCGR_CLK_MODE_ALWAYS 3 #endif struct ccm_softc { device_t dev; struct resource *mem_res; }; static struct ccm_softc *ccm_sc; static inline uint32_t RD4(struct ccm_softc *sc, bus_size_t off) { return (bus_read_4(sc->mem_res, off)); } static inline void WR4(struct ccm_softc *sc, bus_size_t off, uint32_t val) { bus_write_4(sc->mem_res, off, val); } /* * Until we have a fully functional ccm driver which implements the fdt_clock * interface, use the age-old workaround of unconditionally enabling the clocks * for devices we might need to use. The SoC defaults to most clocks enabled, * but the rom boot code and u-boot disable a few of them. We turn on only * what's needed to run the chip plus devices we have drivers for, and turn off * devices we don't yet have drivers for. (Note that USB is not turned on here * because that is one we do when the driver asks for it.) */ static void ccm_init_gates(struct ccm_softc *sc) { uint32_t reg; /* ahpbdma, aipstz 1 & 2 buses */ reg = CCGR0_AIPS_TZ1 | CCGR0_AIPS_TZ2 | CCGR0_ABPHDMA; WR4(sc, CCM_CCGR0, reg); /* enet, epit, gpt */ reg = CCGR1_ENET | CCGR1_EPIT1 | CCGR1_GPT; WR4(sc, CCM_CCGR1, reg); /* ipmux & ipsync (bridges), iomux, i2c */ reg = CCGR2_I2C1 | CCGR2_I2C2 | CCGR2_I2C3 | CCGR2_IIM | CCGR2_IOMUX_IPT | CCGR2_IPMUX1 | CCGR2_IPMUX2 | CCGR2_IPMUX3 | CCGR2_IPSYNC_IP2APB_TZASC1 | CCGR2_IPSYNC_IP2APB_TZASC2 | CCGR2_IPSYNC_VDOA; WR4(sc, CCM_CCGR2, reg); /* DDR memory controller */ reg = CCGR3_OCRAM | CCGR3_MMDC_CORE_IPG | CCGR3_MMDC_CORE_ACLK_FAST | CCGR3_CG11 | CCGR3_CG13; WR4(sc, CCM_CCGR3, reg); /* pl301 bus crossbar */ reg = CCGR4_PL301_MX6QFAST1_S133 | CCGR4_PL301_MX6QPER1_BCH | CCGR4_PL301_MX6QPER2_MAIN; WR4(sc, CCM_CCGR4, reg); /* uarts, ssi, sdma */ reg = CCGR5_SDMA | CCGR5_SSI1 | CCGR5_SSI2 | CCGR5_SSI3 | CCGR5_UART | CCGR5_UART_SERIAL; WR4(sc, CCM_CCGR5, reg); /* usdhc 1-4, usboh3 */ reg = CCGR6_USBOH3 | CCGR6_USDHC1 | CCGR6_USDHC2 | CCGR6_USDHC3 | CCGR6_USDHC4; WR4(sc, CCM_CCGR6, reg); } static int ccm_detach(device_t dev) { struct ccm_softc *sc; sc = device_get_softc(dev); if (sc->mem_res != NULL) bus_release_resource(dev, SYS_RES_MEMORY, 0, sc->mem_res); return (0); } static int ccm_attach(device_t dev) { struct ccm_softc *sc; int err, rid; uint32_t reg; sc = device_get_softc(dev); err = 0; /* Allocate bus_space resources. */ rid = 0; sc->mem_res = bus_alloc_resource_any(dev, SYS_RES_MEMORY, &rid, RF_ACTIVE); if (sc->mem_res == NULL) { device_printf(dev, "Cannot allocate memory resources\n"); err = ENXIO; goto out; } ccm_sc = sc; /* * Configure the Low Power Mode setting to leave the ARM core power on * when a WFI instruction is executed. This lets the MPCore timers and * GIC continue to run, which is helpful when the only thing that can * wake you up is an MPCore Private Timer interrupt delivered via GIC. * * XXX Based on the docs, setting CCM_CGPR_INT_MEM_CLK_LPM shouldn't be * required when the LPM bits are set to LPM_RUN. But experimentally * I've experienced a fairly rare lockup when not setting it. I was * unable to prove conclusively that the lockup was related to power * management or that this definitively fixes it. Revisit this. */ reg = RD4(sc, CCM_CGPR); reg |= CCM_CGPR_INT_MEM_CLK_LPM; WR4(sc, CCM_CGPR, reg); reg = RD4(sc, CCM_CLPCR); reg = (reg & ~CCM_CLPCR_LPM_MASK) | CCM_CLPCR_LPM_RUN; WR4(sc, CCM_CLPCR, reg); ccm_init_gates(sc); err = 0; out: if (err != 0) ccm_detach(dev); return (err); } static int ccm_probe(device_t dev) { if (!ofw_bus_status_okay(dev)) return (ENXIO); if (ofw_bus_is_compatible(dev, "fsl,imx6q-ccm") == 0) return (ENXIO); device_set_desc(dev, "Freescale i.MX6 Clock Control Module"); return (BUS_PROBE_DEFAULT); } void imx_ccm_ssi_configure(device_t _ssidev) { struct ccm_softc *sc; uint32_t reg; sc = ccm_sc; /* * Select PLL4 (Audio PLL) clock multiplexer as source. * PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM). */ reg = RD4(sc, CCM_CSCMR1); reg &= ~(SSI_CLK_SEL_M << SSI1_CLK_SEL_S); reg |= (SSI_CLK_SEL_PLL4 << SSI1_CLK_SEL_S); reg &= ~(SSI_CLK_SEL_M << SSI2_CLK_SEL_S); reg |= (SSI_CLK_SEL_PLL4 << SSI2_CLK_SEL_S); reg &= ~(SSI_CLK_SEL_M << SSI3_CLK_SEL_S); reg |= (SSI_CLK_SEL_PLL4 << SSI3_CLK_SEL_S); WR4(sc, CCM_CSCMR1, reg); /* * Ensure we have set hardware-default values * for pre and post dividers. */ /* SSI1 and SSI3 */ reg = RD4(sc, CCM_CS1CDR); /* Divide by 2 */ reg &= ~(SSI_CLK_PODF_MASK << SSI1_CLK_PODF_SHIFT); reg &= ~(SSI_CLK_PODF_MASK << SSI3_CLK_PODF_SHIFT); reg |= (0x1 << SSI1_CLK_PODF_SHIFT); reg |= (0x1 << SSI3_CLK_PODF_SHIFT); /* Divide by 4 */ reg &= ~(SSI_CLK_PRED_MASK << SSI1_CLK_PRED_SHIFT); reg &= ~(SSI_CLK_PRED_MASK << SSI3_CLK_PRED_SHIFT); reg |= (0x3 << SSI1_CLK_PRED_SHIFT); reg |= (0x3 << SSI3_CLK_PRED_SHIFT); WR4(sc, CCM_CS1CDR, reg); /* SSI2 */ reg = RD4(sc, CCM_CS2CDR); /* Divide by 2 */ reg &= ~(SSI_CLK_PODF_MASK << SSI2_CLK_PODF_SHIFT); reg |= (0x1 << SSI2_CLK_PODF_SHIFT); /* Divide by 4 */ reg &= ~(SSI_CLK_PRED_MASK << SSI2_CLK_PRED_SHIFT); reg |= (0x3 << SSI2_CLK_PRED_SHIFT); WR4(sc, CCM_CS2CDR, reg); } void imx_ccm_usb_enable(device_t _usbdev) { /* * For imx6, the USBOH3 clock gate is bits 0-1 of CCGR6, so no need for * shifting and masking here, just set the low-order two bits to ALWAYS. */ WR4(ccm_sc, CCM_CCGR6, RD4(ccm_sc, CCM_CCGR6) | CCGR_CLK_MODE_ALWAYS); } void imx_ccm_usbphy_enable(device_t _phydev) { /* * XXX Which unit? * Right now it's not clear how to figure from fdt data which phy unit * we're supposed to operate on. Until this is worked out, just enable * both PHYs. */ #if 0 int phy_num, regoff; phy_num = 0; /* XXX */ switch (phy_num) { case 0: regoff = 0; break; case 1: regoff = 0x10; break; default: device_printf(ccm_sc->dev, "Bad PHY number %u,\n", phy_num); return; } imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + regoff, IMX6_ANALOG_CCM_PLL_USB_ENABLE | IMX6_ANALOG_CCM_PLL_USB_POWER | IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS); #else imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + 0, IMX6_ANALOG_CCM_PLL_USB_ENABLE | IMX6_ANALOG_CCM_PLL_USB_POWER | IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS); imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_USB1 + 0x10, IMX6_ANALOG_CCM_PLL_USB_ENABLE | IMX6_ANALOG_CCM_PLL_USB_POWER | IMX6_ANALOG_CCM_PLL_USB_EN_USB_CLKS); #endif } +int +imx6_ccm_sata_enable(void) +{ + uint32_t v; + int timeout; + + /* Un-gate the sata controller. */ + WR4(ccm_sc, CCM_CCGR5, RD4(ccm_sc, CCM_CCGR5) | CCGR5_SATA); + + /* Power up the PLL that feeds ENET/SATA/PCI phys, wait for lock. */ + v = RD4(ccm_sc, CCM_ANALOG_PLL_ENET); + v &= ~CCM_ANALOG_PLL_ENET_POWERDOWN; + WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v); + + for (timeout = 100000; timeout > 0; timeout--) { + if (RD4(ccm_sc, CCM_ANALOG_PLL_ENET) & + CCM_ANALOG_PLL_ENET_LOCK) { + break; + } + } + if (timeout <= 0) { + return ETIMEDOUT; + } + + /* Enable the PLL, and enable its 100mhz output. */ + v |= CCM_ANALOG_PLL_ENET_ENABLE; + v &= ~CCM_ANALOG_PLL_ENET_BYPASS; + WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v); + + v |= CCM_ANALOG_PLL_ENET_ENABLE_100M; + WR4(ccm_sc, CCM_ANALOG_PLL_ENET, v); + + return 0; +} + uint32_t imx_ccm_ipg_hz(void) { return (66000000); } uint32_t imx_ccm_perclk_hz(void) { return (66000000); } uint32_t imx_ccm_sdhci_hz(void) { return (200000000); } uint32_t imx_ccm_uart_hz(void) { return (80000000); } uint32_t imx_ccm_ahb_hz(void) { return (132000000); } void imx_ccm_ipu_enable(int ipu) { struct ccm_softc *sc; uint32_t reg; sc = ccm_sc; reg = RD4(sc, CCM_CCGR3); if (ipu == 1) reg |= CCGR3_IPU1_IPU | CCGR3_IPU1_DI0; else reg |= CCGR3_IPU2_IPU | CCGR3_IPU2_DI0; WR4(sc, CCM_CCGR3, reg); } void imx_ccm_hdmi_enable(void) { struct ccm_softc *sc; uint32_t reg; sc = ccm_sc; reg = RD4(sc, CCM_CCGR2); reg |= CCGR2_HDMI_TX | CCGR2_HDMI_TX_ISFR; WR4(sc, CCM_CCGR2, reg); /* Set HDMI clock to 280MHz */ reg = RD4(sc, CCM_CHSCCDR); reg &= ~(CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK | CHSCCDR_IPU1_DI0_PODF_MASK | CHSCCDR_IPU1_DI0_CLK_SEL_MASK); reg |= (CHSCCDR_PODF_DIVIDE_BY_3 << CHSCCDR_IPU1_DI0_PODF_SHIFT); reg |= (CHSCCDR_IPU_PRE_CLK_540M_PFD << CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT); WR4(sc, CCM_CHSCCDR, reg); reg |= (CHSCCDR_CLK_SEL_LDB_DI0 << CHSCCDR_IPU1_DI0_CLK_SEL_SHIFT); WR4(sc, CCM_CHSCCDR, reg); } uint32_t imx_ccm_get_cacrr(void) { return (RD4(ccm_sc, CCM_CACCR)); } void imx_ccm_set_cacrr(uint32_t divisor) { WR4(ccm_sc, CCM_CACCR, divisor); } static device_method_t ccm_methods[] = { /* Device interface */ DEVMETHOD(device_probe, ccm_probe), DEVMETHOD(device_attach, ccm_attach), DEVMETHOD(device_detach, ccm_detach), DEVMETHOD_END }; static driver_t ccm_driver = { "ccm", ccm_methods, sizeof(struct ccm_softc) }; static devclass_t ccm_devclass; EARLY_DRIVER_MODULE(ccm, simplebus, ccm_driver, ccm_devclass, 0, 0, BUS_PASS_CPU + BUS_PASS_ORDER_EARLY); Index: projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccmreg.h =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccmreg.h (revision 322021) +++ projects/make-check-sandbox/sys/arm/freescale/imx/imx6_ccmreg.h (revision 322022) @@ -1,133 +1,141 @@ /*- * Copyright (c) 2013 Ian Lepore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef IMX6_CCMREG_H #define IMX6_CCMREG_H #define CCM_CACCR 0x010 #define CCM_CBCDR 0x014 #define CBCDR_MMDC_CH1_AXI_PODF_SHIFT 3 #define CBCDR_MMDC_CH1_AXI_PODF_MASK (7 << 3) #define CCM_CSCMR1 0x01C #define SSI1_CLK_SEL_S 10 #define SSI2_CLK_SEL_S 12 #define SSI3_CLK_SEL_S 14 #define SSI_CLK_SEL_M 0x3 #define SSI_CLK_SEL_508_PFD 0 #define SSI_CLK_SEL_454_PFD 1 #define SSI_CLK_SEL_PLL4 2 #define CCM_CSCMR2 0x020 #define CSCMR2_LDB_DI0_IPU_DIV_SHIFT 10 #define CCM_CS1CDR 0x028 #define SSI1_CLK_PODF_SHIFT 0 #define SSI1_CLK_PRED_SHIFT 6 #define SSI3_CLK_PODF_SHIFT 16 #define SSI3_CLK_PRED_SHIFT 22 #define SSI_CLK_PODF_MASK 0x3f #define SSI_CLK_PRED_MASK 0x7 #define CCM_CS2CDR 0x02C #define SSI2_CLK_PODF_SHIFT 0 #define SSI2_CLK_PRED_SHIFT 6 #define LDB_DI0_CLK_SEL_SHIFT 9 #define LDB_DI0_CLK_SEL_MASK (3 << LDB_DI0_CLK_SEL_SHIFT) #define CCM_CHSCCDR 0x034 #define CHSCCDR_IPU1_DI0_PRE_CLK_SEL_MASK (0x7 << 6) #define CHSCCDR_IPU1_DI0_PRE_CLK_SEL_SHIFT 6 #define CHSCCDR_IPU1_DI0_PODF_MASK (0x7 << 3) #define CHSCCDR_IPU1_DI0_PODF_SHIFT 3 #define CHSCCDR_IPU1_DI0_CLK_SEL_MASK (0x7) #define CHSCCDR_IPU1_DI0_CLK_SEL_SHIFT 0 #define CHSCCDR_CLK_SEL_LDB_DI0 3 #define CHSCCDR_PODF_DIVIDE_BY_3 2 #define CHSCCDR_IPU_PRE_CLK_540M_PFD 5 #define CCM_CSCDR2 0x038 #define CCM_CLPCR 0x054 #define CCM_CLPCR_LPM_MASK 0x03 #define CCM_CLPCR_LPM_RUN 0x00 #define CCM_CLPCR_LPM_WAIT 0x01 #define CCM_CLPCR_LPM_STOP 0x02 #define CCM_CGPR 0x064 #define CCM_CGPR_INT_MEM_CLK_LPM (1 << 17) #define CCM_CCGR0 0x068 #define CCGR0_AIPS_TZ1 (0x3 << 0) #define CCGR0_AIPS_TZ2 (0x3 << 2) #define CCGR0_ABPHDMA (0x3 << 4) #define CCM_CCGR1 0x06C #define CCGR1_ENET (0x3 << 10) #define CCGR1_EPIT1 (0x3 << 12) #define CCGR1_EPIT2 (0x3 << 14) #define CCGR1_GPT (0x3 << 20) #define CCGR1_GPT_SERIAL (0x3 << 22) #define CCM_CCGR2 0x070 #define CCGR2_HDMI_TX (0x3 << 0) #define CCGR2_HDMI_TX_ISFR (0x3 << 4) #define CCGR2_I2C1 (0x3 << 6) #define CCGR2_I2C2 (0x3 << 8) #define CCGR2_I2C3 (0x3 << 10) #define CCGR2_IIM (0x3 << 12) #define CCGR2_IOMUX_IPT (0x3 << 14) #define CCGR2_IPMUX1 (0x3 << 16) #define CCGR2_IPMUX2 (0x3 << 18) #define CCGR2_IPMUX3 (0x3 << 20) #define CCGR2_IPSYNC_IP2APB_TZASC1 (0x3 << 22) #define CCGR2_IPSYNC_IP2APB_TZASC2 (0x3 << 24) #define CCGR2_IPSYNC_VDOA (0x3 << 26) #define CCM_CCGR3 0x074 #define CCGR3_IPU1_IPU (0x3 << 0) #define CCGR3_IPU1_DI0 (0x3 << 2) #define CCGR3_IPU1_DI1 (0x3 << 4) #define CCGR3_IPU2_IPU (0x3 << 6) #define CCGR3_IPU2_DI0 (0x3 << 8) #define CCGR3_IPU2_DI1 (0x3 << 10) #define CCGR3_LDB_DI0 (0x3 << 12) #define CCGR3_LDB_DI1 (0x3 << 14) #define CCGR3_MMDC_CORE_ACLK_FAST (0x3 << 20) #define CCGR3_CG11 (0x3 << 22) #define CCGR3_MMDC_CORE_IPG (0x3 << 24) #define CCGR3_CG13 (0x3 << 26) #define CCGR3_OCRAM (0x3 << 28) #define CCM_CCGR4 0x078 #define CCGR4_PL301_MX6QFAST1_S133 (0x3 << 8) #define CCGR4_PL301_MX6QPER1_BCH (0x3 << 12) #define CCGR4_PL301_MX6QPER2_MAIN (0x3 << 14) #define CCM_CCGR5 0x07C +#define CCGR5_SATA (0x3 << 4) #define CCGR5_SDMA (0x3 << 6) #define CCGR5_SSI1 (0x3 << 18) #define CCGR5_SSI2 (0x3 << 20) #define CCGR5_SSI3 (0x3 << 22) #define CCGR5_UART (0x3 << 24) #define CCGR5_UART_SERIAL (0x3 << 26) #define CCM_CCGR6 0x080 #define CCGR6_USBOH3 (0x3 << 0) #define CCGR6_USDHC1 (0x3 << 2) #define CCGR6_USDHC2 (0x3 << 4) #define CCGR6_USDHC3 (0x3 << 6) #define CCGR6_USDHC4 (0x3 << 8) #define CCM_CMEOR 0x088 + +#define CCM_ANALOG_PLL_ENET 0x000040e0 +#define CCM_ANALOG_PLL_ENET_LOCK (1u << 31) +#define CCM_ANALOG_PLL_ENET_ENABLE_100M (1u << 20) /* SATA */ +#define CCM_ANALOG_PLL_ENET_BYPASS (1u << 16) +#define CCM_ANALOG_PLL_ENET_ENABLE (1u << 13) /* Ether */ +#define CCM_ANALOG_PLL_ENET_POWERDOWN (1u << 12) #endif Index: projects/make-check-sandbox/sys/arm/freescale/imx/imx_ccmvar.h =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/imx_ccmvar.h (revision 322021) +++ projects/make-check-sandbox/sys/arm/freescale/imx/imx_ccmvar.h (revision 322022) @@ -1,62 +1,63 @@ /*- * Copyright (c) 2014 Ian Lepore * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef IMX_CCMVAR_H #define IMX_CCMVAR_H /* * We need a clock management system that works across unrelated SoCs and * devices. For now, to keep imx development moving, define some barebones * functionality that can be shared within the imx family by having each SoC * implement functions with a common name. * * The usb enable functions are best-effort. They turn on the usb otg, host, * and phy clocks in a SoC-specific manner, but it may take a lot more than that * to make usb work on a given board. In particular, it can require specific * pinmux setup of gpio pins connected to external phy parts, voltage regulators * and overcurrent detectors, and so on. On such boards, u-boot or other early * board setup code has to handle those things. */ uint32_t imx_ccm_ipg_hz(void); uint32_t imx_ccm_perclk_hz(void); uint32_t imx_ccm_sdhci_hz(void); uint32_t imx_ccm_uart_hz(void); uint32_t imx_ccm_ahb_hz(void); void imx_ccm_usb_enable(device_t _usbdev); void imx_ccm_usbphy_enable(device_t _phydev); void imx_ccm_ssi_configure(device_t _ssidev); void imx_ccm_hdmi_enable(void); void imx_ccm_ipu_enable(int ipu); +int imx6_ccm_sata_enable(void); /* Routines to get and set the arm clock root divisor register. */ uint32_t imx_ccm_get_cacrr(void); void imx_ccm_set_cacrr(uint32_t _divisor); #endif Index: projects/make-check-sandbox/sys/arm/freescale/imx/imx_iomuxreg.h =================================================================== --- projects/make-check-sandbox/sys/arm/freescale/imx/imx_iomuxreg.h (revision 322021) +++ projects/make-check-sandbox/sys/arm/freescale/imx/imx_iomuxreg.h (revision 322022) @@ -1,42 +1,61 @@ /*- * Copyright (c) 2015 Oleksandr Tymoshenko * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ */ #ifndef IMX_IOMUXREG_H #define IMX_IOMUXREG_H -#define IOMUXC_GPR0 0x00 -#define IOMUXC_GPR1 0x04 -#define IOMUXC_GPR2 0x08 -#define IOMUXC_GPR3 0x0C -#define IOMUXC_GPR3_HDMI_MASK (3 << 2) -#define IOMUXC_GPR3_HDMI_IPU1_DI0 (0 << 2) -#define IOMUXC_GPR3_HDMI_IPU1_DI1 (1 << 2) -#define IOMUXC_GPR3_HDMI_IPU2_DI0 (2 << 2) -#define IOMUXC_GPR3_HDMI_IPU2_DI1 (3 << 2) +#define IMX_IOMUXREG_LOWEST_SET_BIT(__mask) ((((__mask) - 1) & (__mask)) ^ (__mask)) +#define IMX_IOMUXREG_SHIFTIN(__x, __mask) ((__x) * IMX_IOMUXREG_LOWEST_SET_BIT(__mask)) + +#define IMX_IOMUXREG_BIT(n) (1 << (n)) +#define IMX_IOMUXREG_BITS(__m, __n) \ + ((IMX_IOMUXREG_BIT(MAX((__m), (__n)) + 1) - 1) ^ (IMX_IOMUXREG_BIT(MIN((__m), (__n))) - 1)) + +#define IOMUXC_GPR0 0x00 +#define IOMUXC_GPR1 0x04 +#define IOMUXC_GPR2 0x08 +#define IOMUXC_GPR3 0x0C +#define IOMUXC_GPR3_HDMI_MASK (3 << 2) +#define IOMUXC_GPR3_HDMI_IPU1_DI0 (0 << 2) +#define IOMUXC_GPR3_HDMI_IPU1_DI1 (1 << 2) +#define IOMUXC_GPR3_HDMI_IPU2_DI0 (2 << 2) +#define IOMUXC_GPR3_HDMI_IPU2_DI1 (3 << 2) + +#define IOMUX_GPR13 0x34 +#define IOMUX_GPR13_SATA_PHY_8(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(26, 24)) +#define IOMUX_GPR13_SATA_PHY_7(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(23, 19)) +#define IOMUX_GPR13_SATA_PHY_6(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(18, 16)) +#define IOMUX_GPR13_SATA_SPEED(n) IMX_IOMUXREG_SHIFTIN(n, (1 << 15)) +#define IOMUX_GPR13_SATA_PHY_5(n) IMX_IOMUXREG_SHIFTIN(n, (1 << 14)) +#define IOMUX_GPR13_SATA_PHY_4(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(13, 11)) +#define IOMUX_GPR13_SATA_PHY_3(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(10, 7)) +#define IOMUX_GPR13_SATA_PHY_2(n) IMX_IOMUXREG_SHIFTIN(n, IMX_IOMUXREG_BITS(6, 2)) +#define IOMUX_GPR13_SATA_PHY_1(n) IMX_IOMUXREG_SHIFTIN(n, (1 << 1)) +#define IOMUX_GPR13_SATA_PHY_0(n) IMX_IOMUXREG_SHIFTIN(n, (1 << 0)) #endif Index: projects/make-check-sandbox/sys/conf/files =================================================================== --- projects/make-check-sandbox/sys/conf/files (revision 322021) +++ projects/make-check-sandbox/sys/conf/files (revision 322022) @@ -1,4718 +1,4730 @@ # $FreeBSD$ # # The long compile-with and dependency lines are required because of # limitations in config: backslash-newline doesn't work in strings, and # dependency lines other than the first are silently ignored. # acpi_quirks.h optional acpi \ dependency "$S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ compile-with "${AWK} -f $S/tools/acpi_quirks2h.awk $S/dev/acpica/acpi_quirks" \ no-obj no-implicit-rule before-depend \ clean "acpi_quirks.h" bhnd_nvram_map.h optional bhnd \ dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ compile-with "sh $S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -h" \ no-obj no-implicit-rule before-depend \ clean "bhnd_nvram_map.h" bhnd_nvram_map_data.h optional bhnd \ dependency "$S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/tools/nvram_map_gen.awk $S/dev/bhnd/nvram/nvram_map" \ compile-with "sh $S/dev/bhnd/tools/nvram_map_gen.sh $S/dev/bhnd/nvram/nvram_map -d" \ no-obj no-implicit-rule before-depend \ clean "bhnd_nvram_map_data.h" # # The 'fdt_dtb_file' target covers an actual DTB file name, which is derived # from the specified source (DTS) file: .dts -> .dtb # fdt_dtb_file optional fdt fdt_dtb_static \ compile-with "sh -c 'MACHINE=${MACHINE} $S/tools/fdt/make_dtb.sh $S ${FDT_DTS_FILE} ${.CURDIR}'" \ no-obj no-implicit-rule before-depend \ clean "${FDT_DTS_FILE:R}.dtb" fdt_static_dtb.h optional fdt fdt_dtb_static \ compile-with "sh -c 'MACHINE=${MACHINE} $S/tools/fdt/make_dtbh.sh ${FDT_DTS_FILE} ${.CURDIR}'" \ dependency "fdt_dtb_file" \ no-obj no-implicit-rule before-depend \ clean "fdt_static_dtb.h" feeder_eq_gen.h optional sound \ dependency "$S/tools/sound/feeder_eq_mkfilter.awk" \ compile-with "${AWK} -f $S/tools/sound/feeder_eq_mkfilter.awk -- ${FEEDER_EQ_PRESETS} > feeder_eq_gen.h" \ no-obj no-implicit-rule before-depend \ clean "feeder_eq_gen.h" feeder_rate_gen.h optional sound \ dependency "$S/tools/sound/feeder_rate_mkfilter.awk" \ compile-with "${AWK} -f $S/tools/sound/feeder_rate_mkfilter.awk -- ${FEEDER_RATE_PRESETS} > feeder_rate_gen.h" \ no-obj no-implicit-rule before-depend \ clean "feeder_rate_gen.h" snd_fxdiv_gen.h optional sound \ dependency "$S/tools/sound/snd_fxdiv_gen.awk" \ compile-with "${AWK} -f $S/tools/sound/snd_fxdiv_gen.awk -- > snd_fxdiv_gen.h" \ no-obj no-implicit-rule before-depend \ clean "snd_fxdiv_gen.h" miidevs.h optional miibus | mii \ dependency "$S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ compile-with "${AWK} -f $S/tools/miidevs2h.awk $S/dev/mii/miidevs" \ no-obj no-implicit-rule before-depend \ clean "miidevs.h" pccarddevs.h standard \ dependency "$S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ compile-with "${AWK} -f $S/tools/pccarddevs2h.awk $S/dev/pccard/pccarddevs" \ no-obj no-implicit-rule before-depend \ clean "pccarddevs.h" kbdmuxmap.h optional kbdmux_dflt_keymap \ compile-with "kbdcontrol -P ${S:S/sys$/share/}/vt/keymaps -P ${S:S/sys$/share/}/syscons/keymaps -L ${KBDMUX_DFLT_KEYMAP} | sed -e 's/^static keymap_t.* = /static keymap_t key_map = /' -e 's/^static accentmap_t.* = /static accentmap_t accent_map = /' > kbdmuxmap.h" \ no-obj no-implicit-rule before-depend \ clean "kbdmuxmap.h" teken_state.h optional sc | vt \ dependency "$S/teken/gensequences $S/teken/sequences" \ compile-with "${AWK} -f $S/teken/gensequences $S/teken/sequences > teken_state.h" \ no-obj no-implicit-rule before-depend \ clean "teken_state.h" usbdevs.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -h" \ no-obj no-implicit-rule before-depend \ clean "usbdevs.h" usbdevs_data.h optional usb \ dependency "$S/tools/usbdevs2h.awk $S/dev/usb/usbdevs" \ compile-with "${AWK} -f $S/tools/usbdevs2h.awk $S/dev/usb/usbdevs -d" \ no-obj no-implicit-rule before-depend \ clean "usbdevs_data.h" cam/cam.c optional scbus cam/cam_compat.c optional scbus cam/cam_iosched.c optional scbus cam/cam_periph.c optional scbus cam/cam_queue.c optional scbus cam/cam_sim.c optional scbus cam/cam_xpt.c optional scbus cam/ata/ata_all.c optional scbus cam/ata/ata_xpt.c optional scbus cam/ata/ata_pmp.c optional scbus cam/nvme/nvme_all.c optional scbus nvme !nvd cam/nvme/nvme_da.c optional scbus nvme da !nvd cam/nvme/nvme_xpt.c optional scbus nvme !nvd cam/scsi/scsi_xpt.c optional scbus cam/scsi/scsi_all.c optional scbus cam/scsi/scsi_cd.c optional cd cam/scsi/scsi_ch.c optional ch cam/ata/ata_da.c optional ada | da cam/ctl/ctl.c optional ctl cam/ctl/ctl_backend.c optional ctl cam/ctl/ctl_backend_block.c optional ctl cam/ctl/ctl_backend_ramdisk.c optional ctl cam/ctl/ctl_cmd_table.c optional ctl cam/ctl/ctl_frontend.c optional ctl cam/ctl/ctl_frontend_cam_sim.c optional ctl cam/ctl/ctl_frontend_ioctl.c optional ctl cam/ctl/ctl_frontend_iscsi.c optional ctl cfiscsi cam/ctl/ctl_ha.c optional ctl cam/ctl/ctl_scsi_all.c optional ctl cam/ctl/ctl_tpc.c optional ctl cam/ctl/ctl_tpc_local.c optional ctl cam/ctl/ctl_error.c optional ctl cam/ctl/ctl_util.c optional ctl cam/ctl/scsi_ctl.c optional ctl cam/mmc/mmc_xpt.c optional scbus mmccam cam/mmc/mmc_da.c optional scbus mmccam da cam/mmc/mmc_sdio.c optional scbus mmccam cam/scsi/scsi_da.c optional da cam/scsi/scsi_low.c optional ncv | nsp | stg cam/scsi/scsi_pass.c optional pass cam/scsi/scsi_pt.c optional pt cam/scsi/scsi_sa.c optional sa cam/scsi/scsi_enc.c optional ses cam/scsi/scsi_enc_ses.c optional ses cam/scsi/scsi_enc_safte.c optional ses cam/scsi/scsi_sg.c optional sg cam/scsi/scsi_targ_bh.c optional targbh cam/scsi/scsi_target.c optional targ cam/scsi/smp_all.c optional scbus # shared between zfs and dtrace cddl/compat/opensolaris/kern/opensolaris.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_cmn_err.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_kmem.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_misc.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_proc.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_sunddi.c optional zfs | dtrace compile-with "${CDDL_C}" cddl/compat/opensolaris/kern/opensolaris_taskq.c optional zfs | dtrace compile-with "${CDDL_C}" # zfs specific cddl/compat/opensolaris/kern/opensolaris_acl.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_dtrace.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_kobj.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_kstat.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_lookup.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_policy.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_string.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_sysevent.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_uio.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_vfs.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_vm.c optional zfs compile-with "${ZFS_C}" cddl/compat/opensolaris/kern/opensolaris_zone.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/acl/acl_common.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/avl/avl.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/nvpair/opensolaris_fnvpair.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/nvpair/opensolaris_nvpair_alloc_fixed.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/unicode/u8_textprep.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfeature_common.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_comutil.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_deleg.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_fletcher.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_ioctl_compat.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_namecheck.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zfs_prop.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zpool_prop.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/common/zfs/zprop_common.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/vnode.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/abd.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/arc.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/blkptr.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/bplist.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/bpobj.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/bptree.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/bqueue.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dbuf.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/ddt.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/ddt_zap.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_diff.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_object.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_objset.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_send.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_traverse.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_tx.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dmu_zfetch.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dnode.c optional zfs compile-with "${ZFS_C}" \ warning "kernel contains CDDL licensed ZFS filesystem" cddl/contrib/opensolaris/uts/common/fs/zfs/dnode_sync.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_bookmark.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dataset.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deadlist.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_deleg.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_destroy.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_dir.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_pool.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_prop.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_scan.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_userhold.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/dsl_synctask.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/gzip.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/lz4.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/lzjb.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/metaslab.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/multilist.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/range_tree.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/refcount.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/rrwlock.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/sa.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/sha256.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/skein_zfs.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/spa.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/spa_config.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/spa_errlog.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/spa_history.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/spa_misc.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/space_map.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/space_reftree.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/trim_map.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/txg.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/uberblock.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/unique.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_cache.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_file.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_geom.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_label.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_mirror.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_missing.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_queue.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_raidz.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/vdev_root.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zap.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zap_leaf.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zap_micro.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfeature.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_acl.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_byteswap.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ctldir.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_debug.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_dir.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fm.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_fuid.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_ioctl.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_log.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_onexit.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_replay.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_rlock.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_sa.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vfsops.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_vnops.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zfs_znode.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zil.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zio.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zio_checksum.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zio_compress.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zio_inject.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zle.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zrlock.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/fs/zfs/zvol.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/callb.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/fm.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/list.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/os/nvpair_alloc_system.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/adler32.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/deflate.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/inffast.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/inflate.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/inftrees.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/opensolaris_crc32.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/trees.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/zmod.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/zmod_subr.c optional zfs compile-with "${ZFS_C}" cddl/contrib/opensolaris/uts/common/zmod/zutil.c optional zfs compile-with "${ZFS_C}" # dtrace specific cddl/contrib/opensolaris/uts/common/dtrace/dtrace.c optional dtrace compile-with "${DTRACE_C}" \ warning "kernel contains CDDL licensed DTRACE" cddl/contrib/opensolaris/uts/common/dtrace/dtrace_xoroshiro128_plus.c optional dtrace compile-with "${DTRACE_C}" cddl/dev/dtmalloc/dtmalloc.c optional dtmalloc | dtraceall compile-with "${CDDL_C}" cddl/dev/profile/profile.c optional dtrace_profile | dtraceall compile-with "${CDDL_C}" cddl/dev/sdt/sdt.c optional dtrace_sdt | dtraceall compile-with "${CDDL_C}" cddl/dev/fbt/fbt.c optional dtrace_fbt | dtraceall compile-with "${FBT_C}" cddl/dev/systrace/systrace.c optional dtrace_systrace | dtraceall compile-with "${CDDL_C}" cddl/dev/prototype.c optional dtrace_prototype | dtraceall compile-with "${CDDL_C}" fs/nfsclient/nfs_clkdtrace.c optional dtnfscl nfscl | dtraceall nfscl compile-with "${CDDL_C}" compat/cloudabi/cloudabi_clock.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_errno.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_fd.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_file.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_futex.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_mem.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_proc.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_random.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_sock.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_thread.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi/cloudabi_vdso.c optional compat_cloudabi32 | compat_cloudabi64 compat/cloudabi32/cloudabi32_fd.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_module.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_poll.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_sock.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_syscalls.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_sysent.c optional compat_cloudabi32 compat/cloudabi32/cloudabi32_thread.c optional compat_cloudabi32 compat/cloudabi64/cloudabi64_fd.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_module.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_poll.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_sock.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_syscalls.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_sysent.c optional compat_cloudabi64 compat/cloudabi64/cloudabi64_thread.c optional compat_cloudabi64 compat/freebsd32/freebsd32_capability.c optional compat_freebsd32 compat/freebsd32/freebsd32_ioctl.c optional compat_freebsd32 compat/freebsd32/freebsd32_misc.c optional compat_freebsd32 compat/freebsd32/freebsd32_syscalls.c optional compat_freebsd32 compat/freebsd32/freebsd32_sysent.c optional compat_freebsd32 contrib/ck/src/ck_array.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_barrier_centralized.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_barrier_combining.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_barrier_dissemination.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_barrier_mcs.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_barrier_tournament.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_epoch.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_hp.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_hs.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_ht.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/ck/src/ck_rhs.c standard compile-with "${NORMAL_C} -I$S/contrib/ck/include" contrib/dev/acpica/common/ahids.c optional acpi acpi_debug contrib/dev/acpica/common/ahuuids.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbcmds.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbconvert.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbdisply.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbexec.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbhistry.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbinput.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbmethod.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbnames.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbobject.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbstats.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbtest.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbutils.c optional acpi acpi_debug contrib/dev/acpica/components/debugger/dbxface.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmbuffer.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmcstyle.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmdeferred.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmnames.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmopcode.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrc.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrcl.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrcl2.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmresrcs.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmutils.c optional acpi acpi_debug contrib/dev/acpica/components/disassembler/dmwalk.c optional acpi acpi_debug contrib/dev/acpica/components/dispatcher/dsargs.c optional acpi contrib/dev/acpica/components/dispatcher/dscontrol.c optional acpi contrib/dev/acpica/components/dispatcher/dsdebug.c optional acpi contrib/dev/acpica/components/dispatcher/dsfield.c optional acpi contrib/dev/acpica/components/dispatcher/dsinit.c optional acpi contrib/dev/acpica/components/dispatcher/dsmethod.c optional acpi contrib/dev/acpica/components/dispatcher/dsmthdat.c optional acpi contrib/dev/acpica/components/dispatcher/dsobject.c optional acpi contrib/dev/acpica/components/dispatcher/dsopcode.c optional acpi contrib/dev/acpica/components/dispatcher/dspkginit.c optional acpi contrib/dev/acpica/components/dispatcher/dsutils.c optional acpi contrib/dev/acpica/components/dispatcher/dswexec.c optional acpi contrib/dev/acpica/components/dispatcher/dswload.c optional acpi contrib/dev/acpica/components/dispatcher/dswload2.c optional acpi contrib/dev/acpica/components/dispatcher/dswscope.c optional acpi contrib/dev/acpica/components/dispatcher/dswstate.c optional acpi contrib/dev/acpica/components/events/evevent.c optional acpi contrib/dev/acpica/components/events/evglock.c optional acpi contrib/dev/acpica/components/events/evgpe.c optional acpi contrib/dev/acpica/components/events/evgpeblk.c optional acpi contrib/dev/acpica/components/events/evgpeinit.c optional acpi contrib/dev/acpica/components/events/evgpeutil.c optional acpi contrib/dev/acpica/components/events/evhandler.c optional acpi contrib/dev/acpica/components/events/evmisc.c optional acpi contrib/dev/acpica/components/events/evregion.c optional acpi contrib/dev/acpica/components/events/evrgnini.c optional acpi contrib/dev/acpica/components/events/evsci.c optional acpi contrib/dev/acpica/components/events/evxface.c optional acpi contrib/dev/acpica/components/events/evxfevnt.c optional acpi contrib/dev/acpica/components/events/evxfgpe.c optional acpi contrib/dev/acpica/components/events/evxfregn.c optional acpi contrib/dev/acpica/components/executer/exconcat.c optional acpi contrib/dev/acpica/components/executer/exconfig.c optional acpi contrib/dev/acpica/components/executer/exconvrt.c optional acpi contrib/dev/acpica/components/executer/excreate.c optional acpi contrib/dev/acpica/components/executer/exdebug.c optional acpi contrib/dev/acpica/components/executer/exdump.c optional acpi contrib/dev/acpica/components/executer/exfield.c optional acpi contrib/dev/acpica/components/executer/exfldio.c optional acpi contrib/dev/acpica/components/executer/exmisc.c optional acpi contrib/dev/acpica/components/executer/exmutex.c optional acpi contrib/dev/acpica/components/executer/exnames.c optional acpi contrib/dev/acpica/components/executer/exoparg1.c optional acpi contrib/dev/acpica/components/executer/exoparg2.c optional acpi contrib/dev/acpica/components/executer/exoparg3.c optional acpi contrib/dev/acpica/components/executer/exoparg6.c optional acpi contrib/dev/acpica/components/executer/exprep.c optional acpi contrib/dev/acpica/components/executer/exregion.c optional acpi contrib/dev/acpica/components/executer/exresnte.c optional acpi contrib/dev/acpica/components/executer/exresolv.c optional acpi contrib/dev/acpica/components/executer/exresop.c optional acpi contrib/dev/acpica/components/executer/exstore.c optional acpi contrib/dev/acpica/components/executer/exstoren.c optional acpi contrib/dev/acpica/components/executer/exstorob.c optional acpi contrib/dev/acpica/components/executer/exsystem.c optional acpi contrib/dev/acpica/components/executer/extrace.c optional acpi contrib/dev/acpica/components/executer/exutils.c optional acpi contrib/dev/acpica/components/hardware/hwacpi.c optional acpi contrib/dev/acpica/components/hardware/hwesleep.c optional acpi contrib/dev/acpica/components/hardware/hwgpe.c optional acpi contrib/dev/acpica/components/hardware/hwpci.c optional acpi contrib/dev/acpica/components/hardware/hwregs.c optional acpi contrib/dev/acpica/components/hardware/hwsleep.c optional acpi contrib/dev/acpica/components/hardware/hwtimer.c optional acpi contrib/dev/acpica/components/hardware/hwvalid.c optional acpi contrib/dev/acpica/components/hardware/hwxface.c optional acpi contrib/dev/acpica/components/hardware/hwxfsleep.c optional acpi contrib/dev/acpica/components/namespace/nsaccess.c optional acpi contrib/dev/acpica/components/namespace/nsalloc.c optional acpi contrib/dev/acpica/components/namespace/nsarguments.c optional acpi contrib/dev/acpica/components/namespace/nsconvert.c optional acpi contrib/dev/acpica/components/namespace/nsdump.c optional acpi contrib/dev/acpica/components/namespace/nseval.c optional acpi contrib/dev/acpica/components/namespace/nsinit.c optional acpi contrib/dev/acpica/components/namespace/nsload.c optional acpi contrib/dev/acpica/components/namespace/nsnames.c optional acpi contrib/dev/acpica/components/namespace/nsobject.c optional acpi contrib/dev/acpica/components/namespace/nsparse.c optional acpi contrib/dev/acpica/components/namespace/nspredef.c optional acpi contrib/dev/acpica/components/namespace/nsprepkg.c optional acpi contrib/dev/acpica/components/namespace/nsrepair.c optional acpi contrib/dev/acpica/components/namespace/nsrepair2.c optional acpi contrib/dev/acpica/components/namespace/nssearch.c optional acpi contrib/dev/acpica/components/namespace/nsutils.c optional acpi contrib/dev/acpica/components/namespace/nswalk.c optional acpi contrib/dev/acpica/components/namespace/nsxfeval.c optional acpi contrib/dev/acpica/components/namespace/nsxfname.c optional acpi contrib/dev/acpica/components/namespace/nsxfobj.c optional acpi contrib/dev/acpica/components/parser/psargs.c optional acpi contrib/dev/acpica/components/parser/psloop.c optional acpi contrib/dev/acpica/components/parser/psobject.c optional acpi contrib/dev/acpica/components/parser/psopcode.c optional acpi contrib/dev/acpica/components/parser/psopinfo.c optional acpi contrib/dev/acpica/components/parser/psparse.c optional acpi contrib/dev/acpica/components/parser/psscope.c optional acpi contrib/dev/acpica/components/parser/pstree.c optional acpi contrib/dev/acpica/components/parser/psutils.c optional acpi contrib/dev/acpica/components/parser/pswalk.c optional acpi contrib/dev/acpica/components/parser/psxface.c optional acpi contrib/dev/acpica/components/resources/rsaddr.c optional acpi contrib/dev/acpica/components/resources/rscalc.c optional acpi contrib/dev/acpica/components/resources/rscreate.c optional acpi contrib/dev/acpica/components/resources/rsdump.c optional acpi acpi_debug contrib/dev/acpica/components/resources/rsdumpinfo.c optional acpi contrib/dev/acpica/components/resources/rsinfo.c optional acpi contrib/dev/acpica/components/resources/rsio.c optional acpi contrib/dev/acpica/components/resources/rsirq.c optional acpi contrib/dev/acpica/components/resources/rslist.c optional acpi contrib/dev/acpica/components/resources/rsmemory.c optional acpi contrib/dev/acpica/components/resources/rsmisc.c optional acpi contrib/dev/acpica/components/resources/rsserial.c optional acpi contrib/dev/acpica/components/resources/rsutils.c optional acpi contrib/dev/acpica/components/resources/rsxface.c optional acpi contrib/dev/acpica/components/tables/tbdata.c optional acpi contrib/dev/acpica/components/tables/tbfadt.c optional acpi contrib/dev/acpica/components/tables/tbfind.c optional acpi contrib/dev/acpica/components/tables/tbinstal.c optional acpi contrib/dev/acpica/components/tables/tbprint.c optional acpi contrib/dev/acpica/components/tables/tbutils.c optional acpi contrib/dev/acpica/components/tables/tbxface.c optional acpi contrib/dev/acpica/components/tables/tbxfload.c optional acpi contrib/dev/acpica/components/tables/tbxfroot.c optional acpi contrib/dev/acpica/components/utilities/utaddress.c optional acpi contrib/dev/acpica/components/utilities/utalloc.c optional acpi contrib/dev/acpica/components/utilities/utascii.c optional acpi contrib/dev/acpica/components/utilities/utbuffer.c optional acpi contrib/dev/acpica/components/utilities/utcache.c optional acpi contrib/dev/acpica/components/utilities/utcopy.c optional acpi contrib/dev/acpica/components/utilities/utdebug.c optional acpi contrib/dev/acpica/components/utilities/utdecode.c optional acpi contrib/dev/acpica/components/utilities/utdelete.c optional acpi contrib/dev/acpica/components/utilities/uterror.c optional acpi contrib/dev/acpica/components/utilities/uteval.c optional acpi contrib/dev/acpica/components/utilities/utexcep.c optional acpi contrib/dev/acpica/components/utilities/utglobal.c optional acpi contrib/dev/acpica/components/utilities/uthex.c optional acpi contrib/dev/acpica/components/utilities/utids.c optional acpi contrib/dev/acpica/components/utilities/utinit.c optional acpi contrib/dev/acpica/components/utilities/utlock.c optional acpi contrib/dev/acpica/components/utilities/utmath.c optional acpi contrib/dev/acpica/components/utilities/utmisc.c optional acpi contrib/dev/acpica/components/utilities/utmutex.c optional acpi contrib/dev/acpica/components/utilities/utnonansi.c optional acpi contrib/dev/acpica/components/utilities/utobject.c optional acpi contrib/dev/acpica/components/utilities/utosi.c optional acpi contrib/dev/acpica/components/utilities/utownerid.c optional acpi contrib/dev/acpica/components/utilities/utpredef.c optional acpi contrib/dev/acpica/components/utilities/utresdecode.c optional acpi acpi_debug contrib/dev/acpica/components/utilities/utresrc.c optional acpi contrib/dev/acpica/components/utilities/utstate.c optional acpi contrib/dev/acpica/components/utilities/utstring.c optional acpi contrib/dev/acpica/components/utilities/utstrtoul64.c optional acpi contrib/dev/acpica/components/utilities/utuuid.c optional acpi acpi_debug contrib/dev/acpica/components/utilities/utxface.c optional acpi contrib/dev/acpica/components/utilities/utxferror.c optional acpi contrib/dev/acpica/components/utilities/utxfinit.c optional acpi contrib/dev/acpica/os_specific/service_layers/osgendbg.c optional acpi acpi_debug contrib/ipfilter/netinet/fil.c optional ipfilter inet \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_auth.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_fil_freebsd.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_frag.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_log.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_nat.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_proxy.c optional ipfilter inet \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_state.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_lookup.c optional ipfilter inet \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN} -Wno-unused -Wno-error -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_pool.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_htable.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_sync.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/mlfk_ipl.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_nat6.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_rules.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_scan.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/ip_dstlist.c optional ipfilter inet \ compile-with "${NORMAL_C} -Wno-unused -I$S/contrib/ipfilter" contrib/ipfilter/netinet/radix_ipf.c optional ipfilter inet \ compile-with "${NORMAL_C} -I$S/contrib/ipfilter" contrib/libfdt/fdt.c optional fdt contrib/libfdt/fdt_ro.c optional fdt contrib/libfdt/fdt_rw.c optional fdt contrib/libfdt/fdt_strerror.c optional fdt contrib/libfdt/fdt_sw.c optional fdt contrib/libfdt/fdt_wip.c optional fdt contrib/libnv/cnvlist.c standard contrib/libnv/dnvlist.c standard contrib/libnv/nvlist.c standard contrib/libnv/nvpair.c standard contrib/ngatm/netnatm/api/cc_conn.c optional ngatm_ccatm \ compile-with "${NORMAL_C_NOWERROR} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_data.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_dump.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_port.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_sig.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/cc_user.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/api/unisap.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/straddr.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/misc/unimsg_common.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/traffic.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_ie.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/msg/uni_msg.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/saal/saal_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_call.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_coord.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_party.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_print.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_reset.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_unimsgcpy.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" contrib/ngatm/netnatm/sig/sig_verify.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" crypto/blowfish/bf_ecb.c optional ipsec | ipsec_support crypto/blowfish/bf_skey.c optional crypto | ipsec | ipsec_support crypto/camellia/camellia.c optional crypto | ipsec | ipsec_support crypto/camellia/camellia-api.c optional crypto | ipsec | ipsec_support crypto/chacha20/chacha20.c optional chacha20 crypto/des/des_ecb.c optional crypto | ipsec | ipsec_support | netsmb crypto/des/des_setkey.c optional crypto | ipsec | ipsec_support | netsmb crypto/rc4/rc4.c optional netgraph_mppc_encryption | kgssapi crypto/rijndael/rijndael-alg-fst.c optional crypto | ekcd | geom_bde | \ ipsec | ipsec_support | random !random_loadable | wlan_ccmp crypto/rijndael/rijndael-api-fst.c optional ekcd | geom_bde | random !random_loadable crypto/rijndael/rijndael-api.c optional crypto | ipsec | ipsec_support | \ wlan_ccmp crypto/sha1.c optional carp | crypto | ipsec | \ ipsec_support | netgraph_mppc_encryption | sctp crypto/sha2/sha256c.c optional crypto | ekcd | geom_bde | ipsec | \ ipsec_support | random !random_loadable | sctp | zfs crypto/sha2/sha512c.c optional crypto | geom_bde | ipsec | \ ipsec_support | zfs crypto/skein/skein.c optional crypto | zfs crypto/skein/skein_block.c optional crypto | zfs crypto/siphash/siphash.c optional inet | inet6 crypto/siphash/siphash_test.c optional inet | inet6 ddb/db_access.c optional ddb ddb/db_break.c optional ddb ddb/db_capture.c optional ddb ddb/db_command.c optional ddb ddb/db_examine.c optional ddb ddb/db_expr.c optional ddb ddb/db_input.c optional ddb ddb/db_lex.c optional ddb ddb/db_main.c optional ddb ddb/db_output.c optional ddb ddb/db_print.c optional ddb ddb/db_ps.c optional ddb ddb/db_run.c optional ddb ddb/db_script.c optional ddb ddb/db_sym.c optional ddb ddb/db_thread.c optional ddb ddb/db_textdump.c optional ddb ddb/db_variables.c optional ddb ddb/db_watch.c optional ddb ddb/db_write_cmd.c optional ddb dev/aac/aac.c optional aac dev/aac/aac_cam.c optional aacp aac dev/aac/aac_debug.c optional aac dev/aac/aac_disk.c optional aac dev/aac/aac_linux.c optional aac compat_linux dev/aac/aac_pci.c optional aac pci dev/aacraid/aacraid.c optional aacraid dev/aacraid/aacraid_cam.c optional aacraid scbus dev/aacraid/aacraid_debug.c optional aacraid dev/aacraid/aacraid_linux.c optional aacraid compat_linux dev/aacraid/aacraid_pci.c optional aacraid pci dev/acpi_support/acpi_wmi.c optional acpi_wmi acpi dev/acpi_support/acpi_asus.c optional acpi_asus acpi dev/acpi_support/acpi_asus_wmi.c optional acpi_asus_wmi acpi dev/acpi_support/acpi_fujitsu.c optional acpi_fujitsu acpi dev/acpi_support/acpi_hp.c optional acpi_hp acpi dev/acpi_support/acpi_ibm.c optional acpi_ibm acpi dev/acpi_support/acpi_panasonic.c optional acpi_panasonic acpi dev/acpi_support/acpi_sony.c optional acpi_sony acpi dev/acpi_support/acpi_toshiba.c optional acpi_toshiba acpi dev/acpi_support/atk0110.c optional aibs acpi dev/acpica/Osd/OsdDebug.c optional acpi dev/acpica/Osd/OsdHardware.c optional acpi dev/acpica/Osd/OsdInterrupt.c optional acpi dev/acpica/Osd/OsdMemory.c optional acpi dev/acpica/Osd/OsdSchedule.c optional acpi dev/acpica/Osd/OsdStream.c optional acpi dev/acpica/Osd/OsdSynch.c optional acpi dev/acpica/Osd/OsdTable.c optional acpi dev/acpica/acpi.c optional acpi dev/acpica/acpi_acad.c optional acpi dev/acpica/acpi_battery.c optional acpi dev/acpica/acpi_button.c optional acpi dev/acpica/acpi_cmbat.c optional acpi dev/acpica/acpi_cpu.c optional acpi dev/acpica/acpi_ec.c optional acpi dev/acpica/acpi_isab.c optional acpi isa dev/acpica/acpi_lid.c optional acpi dev/acpica/acpi_package.c optional acpi dev/acpica/acpi_perf.c optional acpi dev/acpica/acpi_powerres.c optional acpi dev/acpica/acpi_quirk.c optional acpi dev/acpica/acpi_resource.c optional acpi dev/acpica/acpi_container.c optional acpi dev/acpica/acpi_smbat.c optional acpi dev/acpica/acpi_thermal.c optional acpi dev/acpica/acpi_throttle.c optional acpi dev/acpica/acpi_video.c optional acpi_video acpi dev/acpica/acpi_dock.c optional acpi_dock acpi dev/adlink/adlink.c optional adlink dev/advansys/adv_pci.c optional adv pci dev/advansys/advansys.c optional adv dev/advansys/advlib.c optional adv dev/advansys/advmcode.c optional adv dev/advansys/adw_pci.c optional adw pci dev/advansys/adwcam.c optional adw dev/advansys/adwlib.c optional adw dev/advansys/adwmcode.c optional adw dev/ae/if_ae.c optional ae pci dev/age/if_age.c optional age pci dev/agp/agp.c optional agp pci dev/agp/agp_if.m optional agp pci dev/aha/aha.c optional aha dev/aha/aha_isa.c optional aha isa dev/ahci/ahci.c optional ahci dev/ahci/ahciem.c optional ahci dev/ahci/ahci_pci.c optional ahci pci dev/aic/aic.c optional aic dev/aic/aic_pccard.c optional aic pccard dev/aic7xxx/ahc_isa.c optional ahc isa dev/aic7xxx/ahc_pci.c optional ahc pci \ compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}" dev/aic7xxx/ahd_pci.c optional ahd pci \ compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}" dev/aic7xxx/aic7770.c optional ahc dev/aic7xxx/aic79xx.c optional ahd pci dev/aic7xxx/aic79xx_osm.c optional ahd pci dev/aic7xxx/aic79xx_pci.c optional ahd pci dev/aic7xxx/aic79xx_reg_print.c optional ahd pci ahd_reg_pretty_print dev/aic7xxx/aic7xxx.c optional ahc dev/aic7xxx/aic7xxx_93cx6.c optional ahc dev/aic7xxx/aic7xxx_osm.c optional ahc dev/aic7xxx/aic7xxx_pci.c optional ahc pci dev/aic7xxx/aic7xxx_reg_print.c optional ahc ahc_reg_pretty_print dev/al_eth/al_eth.c optional al_eth fdt \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" dev/al_eth/al_init_eth_lm.c optional al_eth fdt \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" dev/al_eth/al_init_eth_kr.c optional al_eth fdt \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_iofic.c optional al_iofic \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_serdes_25g.c optional al_serdes \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_serdes_hssp.c optional al_serdes \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_udma_config.c optional al_udma \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_udma_debug.c optional al_udma \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_udma_iofic.c optional al_udma \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_hal_udma_main.c optional al_udma \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/al_serdes.c optional al_serdes \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/eth/al_hal_eth_kr.c optional al_eth \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" contrib/alpine-hal/eth/al_hal_eth_main.c optional al_eth \ no-depend \ compile-with "${CC} -c -o ${.TARGET} ${CFLAGS} -I$S/contrib/alpine-hal -I$S/contrib/alpine-hal/eth ${PROF} ${.IMPSRC}" dev/alc/if_alc.c optional alc pci dev/ale/if_ale.c optional ale pci dev/alpm/alpm.c optional alpm pci dev/altera/avgen/altera_avgen.c optional altera_avgen dev/altera/avgen/altera_avgen_fdt.c optional altera_avgen fdt dev/altera/avgen/altera_avgen_nexus.c optional altera_avgen dev/altera/sdcard/altera_sdcard.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_disk.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_io.c optional altera_sdcard dev/altera/sdcard/altera_sdcard_fdt.c optional altera_sdcard fdt dev/altera/sdcard/altera_sdcard_nexus.c optional altera_sdcard dev/altera/pio/pio.c optional altera_pio dev/altera/pio/pio_if.m optional altera_pio dev/amdpm/amdpm.c optional amdpm pci | nfpm pci dev/amdsmb/amdsmb.c optional amdsmb pci dev/amr/amr.c optional amr dev/amr/amr_cam.c optional amrp amr dev/amr/amr_disk.c optional amr dev/amr/amr_linux.c optional amr compat_linux dev/amr/amr_pci.c optional amr pci dev/an/if_an.c optional an dev/an/if_an_isa.c optional an isa dev/an/if_an_pccard.c optional an pccard dev/an/if_an_pci.c optional an pci # dev/ata/ata_if.m optional ata | atacore dev/ata/ata-all.c optional ata | atacore dev/ata/ata-dma.c optional ata | atacore dev/ata/ata-lowlevel.c optional ata | atacore dev/ata/ata-sata.c optional ata | atacore dev/ata/ata-card.c optional ata pccard | atapccard dev/ata/ata-isa.c optional ata isa | ataisa dev/ata/ata-pci.c optional ata pci | atapci dev/ata/chipsets/ata-acard.c optional ata pci | ataacard dev/ata/chipsets/ata-acerlabs.c optional ata pci | ataacerlabs dev/ata/chipsets/ata-amd.c optional ata pci | ataamd dev/ata/chipsets/ata-ati.c optional ata pci | ataati dev/ata/chipsets/ata-cenatek.c optional ata pci | atacenatek dev/ata/chipsets/ata-cypress.c optional ata pci | atacypress dev/ata/chipsets/ata-cyrix.c optional ata pci | atacyrix dev/ata/chipsets/ata-highpoint.c optional ata pci | atahighpoint dev/ata/chipsets/ata-intel.c optional ata pci | ataintel dev/ata/chipsets/ata-ite.c optional ata pci | ataite dev/ata/chipsets/ata-jmicron.c optional ata pci | atajmicron dev/ata/chipsets/ata-marvell.c optional ata pci | atamarvell dev/ata/chipsets/ata-micron.c optional ata pci | atamicron dev/ata/chipsets/ata-national.c optional ata pci | atanational dev/ata/chipsets/ata-netcell.c optional ata pci | atanetcell dev/ata/chipsets/ata-nvidia.c optional ata pci | atanvidia dev/ata/chipsets/ata-promise.c optional ata pci | atapromise dev/ata/chipsets/ata-serverworks.c optional ata pci | ataserverworks dev/ata/chipsets/ata-siliconimage.c optional ata pci | atasiliconimage | ataati dev/ata/chipsets/ata-sis.c optional ata pci | atasis dev/ata/chipsets/ata-via.c optional ata pci | atavia # dev/ath/if_ath_pci.c optional ath_pci pci \ compile-with "${NORMAL_C} -I$S/dev/ath" # dev/ath/if_ath_ahb.c optional ath_ahb \ compile-with "${NORMAL_C} -I$S/dev/ath" # dev/ath/if_ath.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_alq.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_beacon.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_btcoex.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_btcoex_mci.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_debug.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_descdma.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_keycache.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_ioctl.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_led.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_lna_div.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_tx.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_tx_edma.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_tx_ht.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_tdma.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_sysctl.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_rx.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_rx_edma.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/if_ath_spectral.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ah_osdep.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" # dev/ath/ath_hal/ah.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_eeprom_v1.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_eeprom_v3.c optional ath_hal | ath_ar5211 | ath_ar5212 \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_eeprom_v14.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_eeprom_v4k.c \ optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_eeprom_9287.c \ optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_hal/ah_regdomain.c optional ath \ compile-with "${NORMAL_C} ${NO_WSHIFT_COUNT_NEGATIVE} ${NO_WSHIFT_COUNT_OVERFLOW} -I$S/dev/ath" # ar5210 dev/ath/ath_hal/ar5210/ar5210_attach.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_beacon.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_interrupts.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_keycache.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_misc.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_phy.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_power.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_recv.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_reset.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5210/ar5210_xmit.c optional ath_hal | ath_ar5210 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar5211 dev/ath/ath_hal/ar5211/ar5211_attach.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_beacon.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_interrupts.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_keycache.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_misc.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_phy.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_power.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_recv.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_reset.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5211/ar5211_xmit.c optional ath_hal | ath_ar5211 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar5212 dev/ath/ath_hal/ar5212/ar5212_ani.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_attach.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_beacon.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_eeprom.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_gpio.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_interrupts.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_keycache.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_misc.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_phy.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_power.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_recv.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_reset.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_rfgain.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5212_xmit.c \ optional ath_hal | ath_ar5212 | ath_ar5416 | ath_ar9160 | ath_ar9280 | \ ath_ar9285 ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar5416 (depends on ar5212) dev/ath/ath_hal/ar5416/ar5416_ani.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_attach.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_beacon.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_btcoex.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_cal.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_cal_iq.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_cal_adcgain.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_cal_adcdc.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_eeprom.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_gpio.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_interrupts.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_keycache.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_misc.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_phy.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_power.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_radar.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_recv.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_reset.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_spectral.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar5416_xmit.c \ optional ath_hal | ath_ar5416 | ath_ar9160 | ath_ar9280 | ath_ar9285 | \ ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9130 (depends upon ar5416) - also requires AH_SUPPORT_AR9130 # # Since this is an embedded MAC SoC, there's no need to compile it into the # default HAL. dev/ath/ath_hal/ar9001/ar9130_attach.c optional ath_ar9130 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9001/ar9130_phy.c optional ath_ar9130 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9001/ar9130_eeprom.c optional ath_ar9130 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9160 (depends on ar5416) dev/ath/ath_hal/ar9001/ar9160_attach.c optional ath_hal | ath_ar9160 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9280 (depends on ar5416) dev/ath/ath_hal/ar9002/ar9280_attach.c optional ath_hal | ath_ar9280 | \ ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9280_olc.c optional ath_hal | ath_ar9280 | \ ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9285 (depends on ar5416 and ar9280) dev/ath/ath_hal/ar9002/ar9285_attach.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285_btcoex.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285_reset.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285_cal.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285_phy.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285_diversity.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9287 (depends on ar5416) dev/ath/ath_hal/ar9002/ar9287_attach.c optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9287_reset.c optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9287_cal.c optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9287_olc.c optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ar9300 contrib/dev/ath/ath_hal/ar9300/ar9300_ani.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_attach.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_beacon.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_eeprom.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal ${NO_WCONSTANT_CONVERSION}" contrib/dev/ath/ath_hal/ar9300/ar9300_freebsd.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_gpio.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_interrupts.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_keycache.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_mci.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_misc.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_paprd.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_phy.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_power.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_radar.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_radio.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_recv.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_recv_ds.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_reset.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal ${NO_WSOMETIMES_UNINITIALIZED} -Wno-unused-function" contrib/dev/ath/ath_hal/ar9300/ar9300_stub.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_stub_funcs.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_spectral.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_timer.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_xmit.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" contrib/dev/ath/ath_hal/ar9300/ar9300_xmit_ds.c optional ath_hal | ath_ar9300 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal -I$S/contrib/dev/ath/ath_hal" # rf backends dev/ath/ath_hal/ar5212/ar2316.c optional ath_rf2316 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar2317.c optional ath_rf2317 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar2413.c optional ath_hal | ath_rf2413 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar2425.c optional ath_hal | ath_rf2425 | ath_rf2417 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5111.c optional ath_hal | ath_rf5111 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5112.c optional ath_hal | ath_rf5112 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5212/ar5413.c optional ath_hal | ath_rf5413 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar5416/ar2133.c optional ath_hal | ath_ar5416 | \ ath_ar9130 | ath_ar9160 | ath_ar9280 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9280.c optional ath_hal | ath_ar9280 | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9285.c optional ath_hal | ath_ar9285 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" dev/ath/ath_hal/ar9002/ar9287.c optional ath_hal | ath_ar9287 \ compile-with "${NORMAL_C} -I$S/dev/ath -I$S/dev/ath/ath_hal" # ath rate control algorithms dev/ath/ath_rate/amrr/amrr.c optional ath_rate_amrr \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/onoe/onoe.c optional ath_rate_onoe \ compile-with "${NORMAL_C} -I$S/dev/ath" dev/ath/ath_rate/sample/sample.c optional ath_rate_sample \ compile-with "${NORMAL_C} -I$S/dev/ath" # ath DFS modules dev/ath/ath_dfs/null/dfs_null.c optional ath \ compile-with "${NORMAL_C} -I$S/dev/ath" # dev/bce/if_bce.c optional bce dev/bfe/if_bfe.c optional bfe dev/bge/if_bge.c optional bge dev/bhnd/bhnd.c optional bhnd dev/bhnd/bhnd_erom.c optional bhnd dev/bhnd/bhnd_erom_if.m optional bhnd dev/bhnd/bhnd_subr.c optional bhnd dev/bhnd/bhnd_bus_if.m optional bhnd dev/bhnd/bhndb/bhnd_bhndb.c optional bhndb bhnd dev/bhnd/bhndb/bhndb.c optional bhndb bhnd dev/bhnd/bhndb/bhndb_bus_if.m optional bhndb bhnd dev/bhnd/bhndb/bhndb_hwdata.c optional bhndb bhnd dev/bhnd/bhndb/bhndb_if.m optional bhndb bhnd dev/bhnd/bhndb/bhndb_pci.c optional bhndb bhnd pci dev/bhnd/bhndb/bhndb_pci_hwdata.c optional bhndb bhnd pci dev/bhnd/bhndb/bhndb_pci_sprom.c optional bhndb bhnd pci dev/bhnd/bhndb/bhndb_subr.c optional bhndb bhnd dev/bhnd/bcma/bcma.c optional bcma bhnd dev/bhnd/bcma/bcma_bhndb.c optional bcma bhnd bhndb dev/bhnd/bcma/bcma_erom.c optional bcma bhnd dev/bhnd/bcma/bcma_subr.c optional bcma bhnd dev/bhnd/cores/chipc/bhnd_chipc_if.m optional bhnd dev/bhnd/cores/chipc/bhnd_sprom_chipc.c optional bhnd dev/bhnd/cores/chipc/bhnd_pmu_chipc.c optional bhnd dev/bhnd/cores/chipc/chipc.c optional bhnd dev/bhnd/cores/chipc/chipc_cfi.c optional bhnd cfi dev/bhnd/cores/chipc/chipc_slicer.c optional bhnd cfi | bhnd spibus dev/bhnd/cores/chipc/chipc_spi.c optional bhnd spibus dev/bhnd/cores/chipc/chipc_subr.c optional bhnd dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl.c optional bhnd dev/bhnd/cores/chipc/pwrctl/bhnd_pwrctl_subr.c optional bhnd dev/bhnd/cores/pci/bhnd_pci.c optional bhnd pci dev/bhnd/cores/pci/bhnd_pci_hostb.c optional bhndb bhnd pci dev/bhnd/cores/pci/bhnd_pcib.c optional bhnd_pcib bhnd pci dev/bhnd/cores/pcie2/bhnd_pcie2.c optional bhnd pci dev/bhnd/cores/pcie2/bhnd_pcie2_hostb.c optional bhndb bhnd pci dev/bhnd/cores/pcie2/bhnd_pcie2b.c optional bhnd_pcie2b bhnd pci dev/bhnd/cores/pmu/bhnd_pmu.c optional bhnd dev/bhnd/cores/pmu/bhnd_pmu_core.c optional bhnd dev/bhnd/cores/pmu/bhnd_pmu_if.m optional bhnd dev/bhnd/cores/pmu/bhnd_pmu_subr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_bcm.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_bcmraw.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_btxt.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_sprom.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_sprom_subr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_data_tlv.c optional bhnd dev/bhnd/nvram/bhnd_nvram_if.m optional bhnd dev/bhnd/nvram/bhnd_nvram_io.c optional bhnd dev/bhnd/nvram/bhnd_nvram_iobuf.c optional bhnd dev/bhnd/nvram/bhnd_nvram_ioptr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_iores.c optional bhnd dev/bhnd/nvram/bhnd_nvram_plist.c optional bhnd dev/bhnd/nvram/bhnd_nvram_store.c optional bhnd dev/bhnd/nvram/bhnd_nvram_store_subr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_subr.c optional bhnd dev/bhnd/nvram/bhnd_nvram_value.c optional bhnd dev/bhnd/nvram/bhnd_nvram_value_fmts.c optional bhnd dev/bhnd/nvram/bhnd_nvram_value_prf.c optional bhnd dev/bhnd/nvram/bhnd_nvram_value_subr.c optional bhnd dev/bhnd/nvram/bhnd_sprom.c optional bhnd dev/bhnd/siba/siba.c optional siba bhnd dev/bhnd/siba/siba_bhndb.c optional siba bhnd bhndb dev/bhnd/siba/siba_erom.c optional siba bhnd dev/bhnd/siba/siba_subr.c optional siba bhnd # dev/bktr/bktr_audio.c optional bktr pci dev/bktr/bktr_card.c optional bktr pci dev/bktr/bktr_core.c optional bktr pci dev/bktr/bktr_i2c.c optional bktr pci smbus dev/bktr/bktr_os.c optional bktr pci dev/bktr/bktr_tuner.c optional bktr pci dev/bktr/msp34xx.c optional bktr pci dev/bnxt/bnxt_hwrm.c optional bnxt iflib pci dev/bnxt/bnxt_sysctl.c optional bnxt iflib pci dev/bnxt/bnxt_txrx.c optional bnxt iflib pci dev/bnxt/if_bnxt.c optional bnxt iflib pci dev/buslogic/bt.c optional bt dev/buslogic/bt_isa.c optional bt isa dev/buslogic/bt_pci.c optional bt pci dev/bwi/bwimac.c optional bwi dev/bwi/bwiphy.c optional bwi dev/bwi/bwirf.c optional bwi dev/bwi/if_bwi.c optional bwi dev/bwi/if_bwi_pci.c optional bwi pci # XXX Work around clang warnings, until maintainer approves fix. dev/bwn/if_bwn.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/bwn/if_bwn_pci.c optional bwn pci bhnd dev/bwn/if_bwn_phy_common.c optional bwn siba_bwn dev/bwn/if_bwn_phy_g.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED} ${NO_WCONSTANT_CONVERSION}" dev/bwn/if_bwn_phy_lp.c optional bwn siba_bwn \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/bwn/if_bwn_phy_n.c optional bwn siba_bwn dev/bwn/if_bwn_util.c optional bwn siba_bwn dev/bwn/bwn_mac.c optional bwn bhnd dev/cardbus/cardbus.c optional cardbus dev/cardbus/cardbus_cis.c optional cardbus dev/cardbus/cardbus_device.c optional cardbus dev/cas/if_cas.c optional cas dev/cfi/cfi_bus_fdt.c optional cfi fdt dev/cfi/cfi_bus_nexus.c optional cfi dev/cfi/cfi_core.c optional cfi dev/cfi/cfi_dev.c optional cfi dev/cfi/cfi_disk.c optional cfid dev/chromebook_platform/chromebook_platform.c optional chromebook_platform dev/ciss/ciss.c optional ciss dev/cm/smc90cx6.c optional cm dev/cmx/cmx.c optional cmx dev/cmx/cmx_pccard.c optional cmx pccard dev/cpufreq/ichss.c optional cpufreq pci dev/cs/if_cs.c optional cs dev/cs/if_cs_isa.c optional cs isa dev/cs/if_cs_pccard.c optional cs pccard dev/cxgb/cxgb_main.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/cxgb_sge.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_mc5.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_vsc7323.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_vsc8211.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_ael1002.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_aq100x.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_mv88e1xxx.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_xgmac.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_t3_hw.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/common/cxgb_tn1010.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/sys/uipc_mvec.c optional cxgb pci \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgb/cxgb_t3fw.c optional cxgb cxgb_t3fw \ compile-with "${NORMAL_C} -I$S/dev/cxgb" dev/cxgbe/t4_if.m optional cxgbe pci dev/cxgbe/t4_iov.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_mp_ring.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_main.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_netmap.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_sched.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_sge.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_l2t.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_tracer.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/t4_vf.c optional cxgbev pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/common/t4_hw.c optional cxgbe pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cxgbe/common/t4vf_hw.c optional cxgbev pci \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/cudbg_common.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/cudbg_flash_utils.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/cudbg_lib.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/cudbg_wtp.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/fastlz.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" +dev/cxgbe/cudbg/fastlz_api.c optional cxgbe \ + compile-with "${NORMAL_C} -I$S/dev/cxgbe" t4fw_cfg.c optional cxgbe \ compile-with "${AWK} -f $S/tools/fw_stub.awk t4fw_cfg.fw:t4fw_cfg t4fw_cfg_uwire.fw:t4fw_cfg_uwire t4fw.fw:t4fw -mt4fw_cfg -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "t4fw_cfg.c" t4fw_cfg.fwo optional cxgbe \ dependency "t4fw_cfg.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t4fw_cfg.fwo" t4fw_cfg.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t4fw_cfg.txt" \ compile-with "${CP} ${.ALLSRC} ${.TARGET}" \ no-obj no-implicit-rule \ clean "t4fw_cfg.fw" t4fw_cfg_uwire.fwo optional cxgbe \ dependency "t4fw_cfg_uwire.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t4fw_cfg_uwire.fwo" t4fw_cfg_uwire.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t4fw_cfg_uwire.txt" \ compile-with "${CP} ${.ALLSRC} ${.TARGET}" \ no-obj no-implicit-rule \ clean "t4fw_cfg_uwire.fw" t4fw.fwo optional cxgbe \ dependency "t4fw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t4fw.fwo" t4fw.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t4fw-1.16.45.0.bin.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "t4fw.fw" t5fw_cfg.c optional cxgbe \ compile-with "${AWK} -f $S/tools/fw_stub.awk t5fw_cfg.fw:t5fw_cfg t5fw.fw:t5fw -mt5fw_cfg -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "t5fw_cfg.c" t5fw_cfg.fwo optional cxgbe \ dependency "t5fw_cfg.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t5fw_cfg.fwo" t5fw_cfg.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t5fw_cfg.txt" \ compile-with "${CP} ${.ALLSRC} ${.TARGET}" \ no-obj no-implicit-rule \ clean "t5fw_cfg.fw" t5fw.fwo optional cxgbe \ dependency "t5fw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t5fw.fwo" t5fw.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t5fw-1.16.45.0.bin.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "t5fw.fw" t6fw_cfg.c optional cxgbe \ compile-with "${AWK} -f $S/tools/fw_stub.awk t6fw_cfg.fw:t6fw_cfg t6fw.fw:t6fw -mt6fw_cfg -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "t6fw_cfg.c" t6fw_cfg.fwo optional cxgbe \ dependency "t6fw_cfg.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t6fw_cfg.fwo" t6fw_cfg.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t6fw_cfg.txt" \ compile-with "${CP} ${.ALLSRC} ${.TARGET}" \ no-obj no-implicit-rule \ clean "t6fw_cfg.fw" t6fw.fwo optional cxgbe \ dependency "t6fw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "t6fw.fwo" t6fw.fw optional cxgbe \ dependency "$S/dev/cxgbe/firmware/t6fw-1.16.45.0.bin.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "t6fw.fw" dev/cxgbe/crypto/t4_crypto.c optional ccr \ compile-with "${NORMAL_C} -I$S/dev/cxgbe" dev/cy/cy.c optional cy dev/cy/cy_isa.c optional cy isa dev/cy/cy_pci.c optional cy pci dev/cyapa/cyapa.c optional cyapa iicbus dev/dc/if_dc.c optional dc pci dev/dc/dcphy.c optional dc pci dev/dc/pnphy.c optional dc pci dev/dcons/dcons.c optional dcons dev/dcons/dcons_crom.c optional dcons_crom dev/dcons/dcons_os.c optional dcons dev/de/if_de.c optional de pci dev/dme/if_dme.c optional dme dev/dpt/dpt_pci.c optional dpt pci dev/dpt/dpt_scsi.c optional dpt dev/drm/ati_pcigart.c optional drm dev/drm/drm_agpsupport.c optional drm dev/drm/drm_auth.c optional drm dev/drm/drm_bufs.c optional drm dev/drm/drm_context.c optional drm dev/drm/drm_dma.c optional drm dev/drm/drm_drawable.c optional drm dev/drm/drm_drv.c optional drm dev/drm/drm_fops.c optional drm dev/drm/drm_hashtab.c optional drm dev/drm/drm_ioctl.c optional drm dev/drm/drm_irq.c optional drm dev/drm/drm_lock.c optional drm dev/drm/drm_memory.c optional drm dev/drm/drm_mm.c optional drm dev/drm/drm_pci.c optional drm dev/drm/drm_scatter.c optional drm dev/drm/drm_sman.c optional drm dev/drm/drm_sysctl.c optional drm dev/drm/drm_vm.c optional drm dev/drm/mach64_dma.c optional mach64drm dev/drm/mach64_drv.c optional mach64drm dev/drm/mach64_irq.c optional mach64drm dev/drm/mach64_state.c optional mach64drm dev/drm/mga_dma.c optional mgadrm dev/drm/mga_drv.c optional mgadrm dev/drm/mga_irq.c optional mgadrm dev/drm/mga_state.c optional mgadrm dev/drm/mga_warp.c optional mgadrm dev/drm/r128_cce.c optional r128drm \ compile-with "${NORMAL_C} ${NO_WCONSTANT_CONVERSION}" dev/drm/r128_drv.c optional r128drm dev/drm/r128_irq.c optional r128drm dev/drm/r128_state.c optional r128drm dev/drm/savage_bci.c optional savagedrm dev/drm/savage_drv.c optional savagedrm dev/drm/savage_state.c optional savagedrm dev/drm/sis_drv.c optional sisdrm dev/drm/sis_ds.c optional sisdrm dev/drm/sis_mm.c optional sisdrm dev/drm/tdfx_drv.c optional tdfxdrm dev/drm/via_dma.c optional viadrm dev/drm/via_dmablit.c optional viadrm dev/drm/via_drv.c optional viadrm dev/drm/via_irq.c optional viadrm dev/drm/via_map.c optional viadrm dev/drm/via_mm.c optional viadrm dev/drm/via_verifier.c optional viadrm dev/drm/via_video.c optional viadrm dev/drm2/drm_agpsupport.c optional drm2 dev/drm2/drm_auth.c optional drm2 dev/drm2/drm_bufs.c optional drm2 dev/drm2/drm_buffer.c optional drm2 dev/drm2/drm_context.c optional drm2 dev/drm2/drm_crtc.c optional drm2 dev/drm2/drm_crtc_helper.c optional drm2 dev/drm2/drm_dma.c optional drm2 dev/drm2/drm_dp_helper.c optional drm2 dev/drm2/drm_dp_iic_helper.c optional drm2 dev/drm2/drm_drv.c optional drm2 dev/drm2/drm_edid.c optional drm2 dev/drm2/drm_fb_helper.c optional drm2 dev/drm2/drm_fops.c optional drm2 dev/drm2/drm_gem.c optional drm2 dev/drm2/drm_gem_names.c optional drm2 dev/drm2/drm_global.c optional drm2 dev/drm2/drm_hashtab.c optional drm2 dev/drm2/drm_ioctl.c optional drm2 dev/drm2/drm_irq.c optional drm2 dev/drm2/drm_linux_list_sort.c optional drm2 dev/drm2/drm_lock.c optional drm2 dev/drm2/drm_memory.c optional drm2 dev/drm2/drm_mm.c optional drm2 dev/drm2/drm_modes.c optional drm2 dev/drm2/drm_pci.c optional drm2 dev/drm2/drm_platform.c optional drm2 dev/drm2/drm_scatter.c optional drm2 dev/drm2/drm_stub.c optional drm2 dev/drm2/drm_sysctl.c optional drm2 dev/drm2/drm_vm.c optional drm2 dev/drm2/drm_os_freebsd.c optional drm2 dev/drm2/ttm/ttm_agp_backend.c optional drm2 dev/drm2/ttm/ttm_lock.c optional drm2 dev/drm2/ttm/ttm_object.c optional drm2 dev/drm2/ttm/ttm_tt.c optional drm2 dev/drm2/ttm/ttm_bo_util.c optional drm2 dev/drm2/ttm/ttm_bo.c optional drm2 dev/drm2/ttm/ttm_bo_manager.c optional drm2 dev/drm2/ttm/ttm_execbuf_util.c optional drm2 dev/drm2/ttm/ttm_memory.c optional drm2 dev/drm2/ttm/ttm_page_alloc.c optional drm2 dev/drm2/ttm/ttm_bo_vm.c optional drm2 dev/drm2/ati_pcigart.c optional drm2 agp pci dev/ed/if_ed.c optional ed dev/ed/if_ed_novell.c optional ed dev/ed/if_ed_rtl80x9.c optional ed dev/ed/if_ed_pccard.c optional ed pccard dev/ed/if_ed_pci.c optional ed pci dev/efidev/efidev.c optional efirt dev/e1000/if_em.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/em_txrx.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/igb_txrx.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_80003es2lan.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82540.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82541.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82542.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82543.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82571.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_82575.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_ich8lan.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_i210.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_api.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_mac.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_manage.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_nvm.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_phy.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_vf.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_mbx.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/e1000/e1000_osdep.c optional em \ compile-with "${NORMAL_C} -I$S/dev/e1000" dev/et/if_et.c optional et dev/ena/ena.c optional ena \ compile-with "${NORMAL_C} -I$S/contrib" dev/ena/ena_sysctl.c optional ena \ compile-with "${NORMAL_C} -I$S/contrib" contrib/ena-com/ena_com.c optional ena contrib/ena-com/ena_eth_com.c optional ena dev/ep/if_ep.c optional ep dev/ep/if_ep_isa.c optional ep isa dev/ep/if_ep_pccard.c optional ep pccard dev/esp/esp_pci.c optional esp pci dev/esp/ncr53c9x.c optional esp dev/etherswitch/arswitch/arswitch.c optional arswitch dev/etherswitch/arswitch/arswitch_reg.c optional arswitch dev/etherswitch/arswitch/arswitch_phy.c optional arswitch dev/etherswitch/arswitch/arswitch_8216.c optional arswitch dev/etherswitch/arswitch/arswitch_8226.c optional arswitch dev/etherswitch/arswitch/arswitch_8316.c optional arswitch dev/etherswitch/arswitch/arswitch_8327.c optional arswitch dev/etherswitch/arswitch/arswitch_7240.c optional arswitch dev/etherswitch/arswitch/arswitch_9340.c optional arswitch dev/etherswitch/arswitch/arswitch_vlans.c optional arswitch dev/etherswitch/etherswitch.c optional etherswitch dev/etherswitch/etherswitch_if.m optional etherswitch dev/etherswitch/ip17x/ip17x.c optional ip17x dev/etherswitch/ip17x/ip175c.c optional ip17x dev/etherswitch/ip17x/ip175d.c optional ip17x dev/etherswitch/ip17x/ip17x_phy.c optional ip17x dev/etherswitch/ip17x/ip17x_vlans.c optional ip17x dev/etherswitch/miiproxy.c optional miiproxy dev/etherswitch/rtl8366/rtl8366rb.c optional rtl8366rb dev/etherswitch/e6000sw/e6000sw.c optional e6000sw dev/etherswitch/e6000sw/e6060sw.c optional e6060sw dev/etherswitch/infineon/adm6996fc.c optional adm6996fc dev/etherswitch/micrel/ksz8995ma.c optional ksz8995ma dev/etherswitch/ukswitch/ukswitch.c optional ukswitch dev/evdev/cdev.c optional evdev dev/evdev/evdev.c optional evdev dev/evdev/evdev_mt.c optional evdev dev/evdev/evdev_utils.c optional evdev dev/evdev/uinput.c optional evdev uinput dev/ex/if_ex.c optional ex dev/ex/if_ex_isa.c optional ex isa dev/ex/if_ex_pccard.c optional ex pccard dev/exca/exca.c optional cbb dev/extres/clk/clk.c optional ext_resources clk fdt dev/extres/clk/clkdev_if.m optional ext_resources clk fdt dev/extres/clk/clknode_if.m optional ext_resources clk fdt dev/extres/clk/clk_bus.c optional ext_resources clk fdt dev/extres/clk/clk_div.c optional ext_resources clk fdt dev/extres/clk/clk_fixed.c optional ext_resources clk fdt dev/extres/clk/clk_gate.c optional ext_resources clk fdt dev/extres/clk/clk_mux.c optional ext_resources clk fdt dev/extres/phy/phy.c optional ext_resources phy fdt dev/extres/phy/phy_if.m optional ext_resources phy fdt dev/extres/hwreset/hwreset.c optional ext_resources hwreset fdt dev/extres/hwreset/hwreset_if.m optional ext_resources hwreset fdt dev/extres/regulator/regdev_if.m optional ext_resources regulator fdt dev/extres/regulator/regnode_if.m optional ext_resources regulator fdt dev/extres/regulator/regulator.c optional ext_resources regulator fdt dev/extres/regulator/regulator_bus.c optional ext_resources regulator fdt dev/extres/regulator/regulator_fixed.c optional ext_resources regulator fdt dev/fb/fbd.c optional fbd | vt dev/fb/fb_if.m standard dev/fb/splash.c optional sc splash dev/fdt/fdt_clock.c optional fdt fdt_clock dev/fdt/fdt_clock_if.m optional fdt fdt_clock dev/fdt/fdt_common.c optional fdt dev/fdt/fdt_pinctrl.c optional fdt fdt_pinctrl dev/fdt/fdt_pinctrl_if.m optional fdt fdt_pinctrl dev/fdt/fdt_slicer.c optional fdt cfi | fdt nand | fdt mx25l dev/fdt/fdt_static_dtb.S optional fdt fdt_dtb_static \ dependency "fdt_dtb_file" dev/fdt/simplebus.c optional fdt dev/fe/if_fe.c optional fe dev/fe/if_fe_pccard.c optional fe pccard dev/filemon/filemon.c optional filemon dev/firewire/firewire.c optional firewire dev/firewire/fwcrom.c optional firewire dev/firewire/fwdev.c optional firewire dev/firewire/fwdma.c optional firewire dev/firewire/fwmem.c optional firewire dev/firewire/fwohci.c optional firewire dev/firewire/fwohci_pci.c optional firewire pci dev/firewire/if_fwe.c optional fwe dev/firewire/if_fwip.c optional fwip dev/firewire/sbp.c optional sbp dev/firewire/sbp_targ.c optional sbp_targ dev/flash/at45d.c optional at45d dev/flash/mx25l.c optional mx25l dev/fxp/if_fxp.c optional fxp dev/fxp/inphy.c optional fxp dev/gem/if_gem.c optional gem dev/gem/if_gem_pci.c optional gem pci dev/gem/if_gem_sbus.c optional gem sbus dev/gpio/gpiobacklight.c optional gpiobacklight fdt dev/gpio/gpiokeys.c optional gpiokeys fdt dev/gpio/gpiokeys_codes.c optional gpiokeys fdt dev/gpio/gpiobus.c optional gpio \ dependency "gpiobus_if.h" dev/gpio/gpioc.c optional gpio \ dependency "gpio_if.h" dev/gpio/gpioiic.c optional gpioiic dev/gpio/gpioled.c optional gpioled !fdt dev/gpio/gpioled_fdt.c optional gpioled fdt dev/gpio/gpiopower.c optional gpiopower fdt dev/gpio/gpioregulator.c optional gpioregulator fdt ext_resources dev/gpio/gpiospi.c optional gpiospi dev/gpio/gpioths.c optional gpioths dev/gpio/gpio_if.m optional gpio dev/gpio/gpiobus_if.m optional gpio dev/gpio/gpiopps.c optional gpiopps dev/gpio/ofw_gpiobus.c optional fdt gpio dev/hifn/hifn7751.c optional hifn dev/hme/if_hme.c optional hme dev/hme/if_hme_pci.c optional hme pci dev/hme/if_hme_sbus.c optional hme sbus dev/hptiop/hptiop.c optional hptiop scbus dev/hwpmc/hwpmc_logging.c optional hwpmc dev/hwpmc/hwpmc_mod.c optional hwpmc dev/hwpmc/hwpmc_soft.c optional hwpmc dev/ichiic/ig4_acpi.c optional ig4 acpi iicbus dev/ichiic/ig4_iic.c optional ig4 iicbus dev/ichiic/ig4_pci.c optional ig4 pci iicbus dev/ichsmb/ichsmb.c optional ichsmb dev/ichsmb/ichsmb_pci.c optional ichsmb pci dev/ida/ida.c optional ida dev/ida/ida_disk.c optional ida dev/ida/ida_pci.c optional ida pci dev/iicbus/ad7418.c optional ad7418 dev/iicbus/ds1307.c optional ds1307 dev/iicbus/ds133x.c optional ds133x dev/iicbus/ds1374.c optional ds1374 dev/iicbus/ds1672.c optional ds1672 dev/iicbus/ds3231.c optional ds3231 dev/iicbus/icee.c optional icee dev/iicbus/if_ic.c optional ic dev/iicbus/iic.c optional iic dev/iicbus/iic_recover_bus.c optional iicbus dev/iicbus/iicbb.c optional iicbb dev/iicbus/iicbb_if.m optional iicbb dev/iicbus/iicbus.c optional iicbus dev/iicbus/iicbus_if.m optional iicbus dev/iicbus/iiconf.c optional iicbus dev/iicbus/iicsmb.c optional iicsmb \ dependency "iicbus_if.h" dev/iicbus/iicoc.c optional iicoc dev/iicbus/isl12xx.c optional isl12xx dev/iicbus/lm75.c optional lm75 dev/iicbus/nxprtc.c optional nxprtc | pcf8563 dev/iicbus/ofw_iicbus.c optional fdt iicbus dev/iicbus/s35390a.c optional s35390a dev/iir/iir.c optional iir dev/iir/iir_ctrl.c optional iir dev/iir/iir_pci.c optional iir pci dev/intpm/intpm.c optional intpm pci # XXX Work around clang warning, until maintainer approves fix. dev/ips/ips.c optional ips \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/ips/ips_commands.c optional ips dev/ips/ips_disk.c optional ips dev/ips/ips_ioctl.c optional ips dev/ips/ips_pci.c optional ips pci dev/ipw/if_ipw.c optional ipw ipwbssfw.c optional ipwbssfw | ipwfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk ipw_bss.fw:ipw_bss:130 -lintel_ipw -mipw_bss -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "ipwbssfw.c" ipw_bss.fwo optional ipwbssfw | ipwfw \ dependency "ipw_bss.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "ipw_bss.fwo" ipw_bss.fw optional ipwbssfw | ipwfw \ dependency "$S/contrib/dev/ipw/ipw2100-1.3.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "ipw_bss.fw" ipwibssfw.c optional ipwibssfw | ipwfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk ipw_ibss.fw:ipw_ibss:130 -lintel_ipw -mipw_ibss -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "ipwibssfw.c" ipw_ibss.fwo optional ipwibssfw | ipwfw \ dependency "ipw_ibss.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "ipw_ibss.fwo" ipw_ibss.fw optional ipwibssfw | ipwfw \ dependency "$S/contrib/dev/ipw/ipw2100-1.3-i.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "ipw_ibss.fw" ipwmonitorfw.c optional ipwmonitorfw | ipwfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk ipw_monitor.fw:ipw_monitor:130 -lintel_ipw -mipw_monitor -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "ipwmonitorfw.c" ipw_monitor.fwo optional ipwmonitorfw | ipwfw \ dependency "ipw_monitor.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "ipw_monitor.fwo" ipw_monitor.fw optional ipwmonitorfw | ipwfw \ dependency "$S/contrib/dev/ipw/ipw2100-1.3-p.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "ipw_monitor.fw" dev/iscsi/icl.c optional iscsi dev/iscsi/icl_conn_if.m optional cfiscsi | iscsi dev/iscsi/icl_soft.c optional iscsi dev/iscsi/icl_soft_proxy.c optional iscsi dev/iscsi/iscsi.c optional iscsi scbus dev/iscsi_initiator/iscsi.c optional iscsi_initiator scbus dev/iscsi_initiator/iscsi_subr.c optional iscsi_initiator scbus dev/iscsi_initiator/isc_cam.c optional iscsi_initiator scbus dev/iscsi_initiator/isc_soc.c optional iscsi_initiator scbus dev/iscsi_initiator/isc_sm.c optional iscsi_initiator scbus dev/iscsi_initiator/isc_subr.c optional iscsi_initiator scbus dev/ismt/ismt.c optional ismt dev/isl/isl.c optional isl iicbus dev/isp/isp.c optional isp dev/isp/isp_freebsd.c optional isp dev/isp/isp_library.c optional isp dev/isp/isp_pci.c optional isp pci dev/isp/isp_sbus.c optional isp sbus dev/isp/isp_target.c optional isp dev/ispfw/ispfw.c optional ispfw dev/iwi/if_iwi.c optional iwi iwibssfw.c optional iwibssfw | iwifw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwi_bss.fw:iwi_bss:300 -lintel_iwi -miwi_bss -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwibssfw.c" iwi_bss.fwo optional iwibssfw | iwifw \ dependency "iwi_bss.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwi_bss.fwo" iwi_bss.fw optional iwibssfw | iwifw \ dependency "$S/contrib/dev/iwi/ipw2200-bss.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwi_bss.fw" iwiibssfw.c optional iwiibssfw | iwifw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwi_ibss.fw:iwi_ibss:300 -lintel_iwi -miwi_ibss -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwiibssfw.c" iwi_ibss.fwo optional iwiibssfw | iwifw \ dependency "iwi_ibss.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwi_ibss.fwo" iwi_ibss.fw optional iwiibssfw | iwifw \ dependency "$S/contrib/dev/iwi/ipw2200-ibss.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwi_ibss.fw" iwimonitorfw.c optional iwimonitorfw | iwifw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwi_monitor.fw:iwi_monitor:300 -lintel_iwi -miwi_monitor -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwimonitorfw.c" iwi_monitor.fwo optional iwimonitorfw | iwifw \ dependency "iwi_monitor.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwi_monitor.fwo" iwi_monitor.fw optional iwimonitorfw | iwifw \ dependency "$S/contrib/dev/iwi/ipw2200-sniffer.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwi_monitor.fw" dev/iwm/if_iwm.c optional iwm dev/iwm/if_iwm_7000.c optional iwm dev/iwm/if_iwm_8000.c optional iwm dev/iwm/if_iwm_binding.c optional iwm dev/iwm/if_iwm_fw.c optional iwm dev/iwm/if_iwm_led.c optional iwm dev/iwm/if_iwm_mac_ctxt.c optional iwm dev/iwm/if_iwm_notif_wait.c optional iwm dev/iwm/if_iwm_pcie_trans.c optional iwm dev/iwm/if_iwm_phy_ctxt.c optional iwm dev/iwm/if_iwm_phy_db.c optional iwm dev/iwm/if_iwm_power.c optional iwm dev/iwm/if_iwm_scan.c optional iwm dev/iwm/if_iwm_sf.c optional iwm dev/iwm/if_iwm_sta.c optional iwm dev/iwm/if_iwm_time_event.c optional iwm dev/iwm/if_iwm_util.c optional iwm iwm3160fw.c optional iwm3160fw | iwmfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwm3160.fw:iwm3160fw -miwm3160fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwm3160fw.c" iwm3160fw.fwo optional iwm3160fw | iwmfw \ dependency "iwm3160.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwm3160fw.fwo" iwm3160.fw optional iwm3160fw | iwmfw \ dependency "$S/contrib/dev/iwm/iwm-3160-17.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwm3160.fw" iwm7260fw.c optional iwm7260fw | iwmfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwm7260.fw:iwm7260fw -miwm7260fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwm7260fw.c" iwm7260fw.fwo optional iwm7260fw | iwmfw \ dependency "iwm7260.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwm7260fw.fwo" iwm7260.fw optional iwm7260fw | iwmfw \ dependency "$S/contrib/dev/iwm/iwm-7260-17.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwm7260.fw" iwm7265fw.c optional iwm7265fw | iwmfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwm7265.fw:iwm7265fw -miwm7265fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwm7265fw.c" iwm7265fw.fwo optional iwm7265fw | iwmfw \ dependency "iwm7265.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwm7265fw.fwo" iwm7265.fw optional iwm7265fw | iwmfw \ dependency "$S/contrib/dev/iwm/iwm-7265-17.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwm7265.fw" iwm7265Dfw.c optional iwm7265Dfw | iwmfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwm7265D.fw:iwm7265Dfw -miwm7265Dfw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwm7265Dfw.c" iwm7265Dfw.fwo optional iwm7265Dfw | iwmfw \ dependency "iwm7265D.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwm7265Dfw.fwo" iwm7265D.fw optional iwm7265Dfw | iwmfw \ dependency "$S/contrib/dev/iwm/iwm-7265D-17.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwm7265D.fw" iwm8000Cfw.c optional iwm8000Cfw | iwmfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwm8000C.fw:iwm8000Cfw -miwm8000Cfw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwm8000Cfw.c" iwm8000Cfw.fwo optional iwm8000Cfw | iwmfw \ dependency "iwm8000C.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwm8000Cfw.fwo" iwm8000C.fw optional iwm8000Cfw | iwmfw \ dependency "$S/contrib/dev/iwm/iwm-8000C-16.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwm8000C.fw" dev/iwn/if_iwn.c optional iwn iwn1000fw.c optional iwn1000fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn1000.fw:iwn1000fw -miwn1000fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn1000fw.c" iwn1000fw.fwo optional iwn1000fw | iwnfw \ dependency "iwn1000.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn1000fw.fwo" iwn1000.fw optional iwn1000fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-1000-39.31.5.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn1000.fw" iwn100fw.c optional iwn100fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn100.fw:iwn100fw -miwn100fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn100fw.c" iwn100fw.fwo optional iwn100fw | iwnfw \ dependency "iwn100.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn100fw.fwo" iwn100.fw optional iwn100fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-100-39.31.5.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn100.fw" iwn105fw.c optional iwn105fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn105.fw:iwn105fw -miwn105fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn105fw.c" iwn105fw.fwo optional iwn105fw | iwnfw \ dependency "iwn105.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn105fw.fwo" iwn105.fw optional iwn105fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-105-6-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn105.fw" iwn135fw.c optional iwn135fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn135.fw:iwn135fw -miwn135fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn135fw.c" iwn135fw.fwo optional iwn135fw | iwnfw \ dependency "iwn135.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn135fw.fwo" iwn135.fw optional iwn135fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-135-6-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn135.fw" iwn2000fw.c optional iwn2000fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn2000.fw:iwn2000fw -miwn2000fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn2000fw.c" iwn2000fw.fwo optional iwn2000fw | iwnfw \ dependency "iwn2000.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn2000fw.fwo" iwn2000.fw optional iwn2000fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-2000-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn2000.fw" iwn2030fw.c optional iwn2030fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn2030.fw:iwn2030fw -miwn2030fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn2030fw.c" iwn2030fw.fwo optional iwn2030fw | iwnfw \ dependency "iwn2030.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn2030fw.fwo" iwn2030.fw optional iwn2030fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwnwifi-2030-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn2030.fw" iwn4965fw.c optional iwn4965fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn4965.fw:iwn4965fw -miwn4965fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn4965fw.c" iwn4965fw.fwo optional iwn4965fw | iwnfw \ dependency "iwn4965.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn4965fw.fwo" iwn4965.fw optional iwn4965fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-4965-228.61.2.24.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn4965.fw" iwn5000fw.c optional iwn5000fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn5000.fw:iwn5000fw -miwn5000fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn5000fw.c" iwn5000fw.fwo optional iwn5000fw | iwnfw \ dependency "iwn5000.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn5000fw.fwo" iwn5000.fw optional iwn5000fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-5000-8.83.5.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn5000.fw" iwn5150fw.c optional iwn5150fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn5150.fw:iwn5150fw -miwn5150fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn5150fw.c" iwn5150fw.fwo optional iwn5150fw | iwnfw \ dependency "iwn5150.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn5150fw.fwo" iwn5150.fw optional iwn5150fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-5150-8.24.2.2.fw.uu"\ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn5150.fw" iwn6000fw.c optional iwn6000fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn6000.fw:iwn6000fw -miwn6000fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn6000fw.c" iwn6000fw.fwo optional iwn6000fw | iwnfw \ dependency "iwn6000.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn6000fw.fwo" iwn6000.fw optional iwn6000fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-6000-9.221.4.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn6000.fw" iwn6000g2afw.c optional iwn6000g2afw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn6000g2a.fw:iwn6000g2afw -miwn6000g2afw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn6000g2afw.c" iwn6000g2afw.fwo optional iwn6000g2afw | iwnfw \ dependency "iwn6000g2a.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn6000g2afw.fwo" iwn6000g2a.fw optional iwn6000g2afw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-6000g2a-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn6000g2a.fw" iwn6000g2bfw.c optional iwn6000g2bfw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn6000g2b.fw:iwn6000g2bfw -miwn6000g2bfw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn6000g2bfw.c" iwn6000g2bfw.fwo optional iwn6000g2bfw | iwnfw \ dependency "iwn6000g2b.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn6000g2bfw.fwo" iwn6000g2b.fw optional iwn6000g2bfw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-6000g2b-18.168.6.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn6000g2b.fw" iwn6050fw.c optional iwn6050fw | iwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk iwn6050.fw:iwn6050fw -miwn6050fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "iwn6050fw.c" iwn6050fw.fwo optional iwn6050fw | iwnfw \ dependency "iwn6050.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "iwn6050fw.fwo" iwn6050.fw optional iwn6050fw | iwnfw \ dependency "$S/contrib/dev/iwn/iwlwifi-6050-41.28.5.1.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "iwn6050.fw" dev/ixgb/if_ixgb.c optional ixgb dev/ixgb/ixgb_ee.c optional ixgb dev/ixgb/ixgb_hw.c optional ixgb dev/ixgbe/if_ix.c optional ix inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP" dev/ixgbe/if_ixv.c optional ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe -DSMP" dev/ixgbe/if_bypass.c optional ix inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_netmap.c optional ix inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/if_fdir.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/if_sriov.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ix_txrx.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_osdep.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_phy.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_api.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_common.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_mbx.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_vf.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_82598.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_82599.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_x540.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_x550.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_dcb.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_dcb_82598.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/ixgbe/ixgbe_dcb_82599.c optional ix inet | ixv inet \ compile-with "${NORMAL_C} -I$S/dev/ixgbe" dev/jedec_ts/jedec_ts.c optional jedec_ts smbus dev/jme/if_jme.c optional jme pci dev/joy/joy.c optional joy dev/joy/joy_isa.c optional joy isa dev/kbd/kbd.c optional atkbd | pckbd | sc | ukbd | vt dev/kbdmux/kbdmux.c optional kbdmux dev/ksyms/ksyms.c optional ksyms dev/le/am7990.c optional le dev/le/am79900.c optional le dev/le/if_le_pci.c optional le pci dev/le/lance.c optional le dev/led/led.c standard dev/lge/if_lge.c optional lge dev/lmc/if_lmc.c optional lmc dev/malo/if_malo.c optional malo dev/malo/if_malohal.c optional malo dev/malo/if_malo_pci.c optional malo pci dev/mc146818/mc146818.c optional mc146818 dev/md/md.c optional md dev/mdio/mdio_if.m optional miiproxy | mdio dev/mdio/mdio.c optional miiproxy | mdio dev/mem/memdev.c optional mem dev/mem/memutil.c optional mem dev/mfi/mfi.c optional mfi dev/mfi/mfi_debug.c optional mfi dev/mfi/mfi_pci.c optional mfi pci dev/mfi/mfi_disk.c optional mfi dev/mfi/mfi_syspd.c optional mfi dev/mfi/mfi_tbolt.c optional mfi dev/mfi/mfi_linux.c optional mfi compat_linux dev/mfi/mfi_cam.c optional mfip scbus dev/mii/acphy.c optional miibus | acphy dev/mii/amphy.c optional miibus | amphy dev/mii/atphy.c optional miibus | atphy dev/mii/axphy.c optional miibus | axphy dev/mii/bmtphy.c optional miibus | bmtphy dev/mii/brgphy.c optional miibus | brgphy dev/mii/ciphy.c optional miibus | ciphy dev/mii/e1000phy.c optional miibus | e1000phy dev/mii/gentbi.c optional miibus | gentbi dev/mii/icsphy.c optional miibus | icsphy dev/mii/ip1000phy.c optional miibus | ip1000phy dev/mii/jmphy.c optional miibus | jmphy dev/mii/lxtphy.c optional miibus | lxtphy dev/mii/micphy.c optional miibus fdt | micphy fdt dev/mii/mii.c optional miibus | mii dev/mii/mii_bitbang.c optional miibus | mii_bitbang dev/mii/mii_physubr.c optional miibus | mii dev/mii/mii_fdt.c optional miibus fdt | mii fdt dev/mii/miibus_if.m optional miibus | mii dev/mii/mlphy.c optional miibus | mlphy dev/mii/nsgphy.c optional miibus | nsgphy dev/mii/nsphy.c optional miibus | nsphy dev/mii/nsphyter.c optional miibus | nsphyter dev/mii/pnaphy.c optional miibus | pnaphy dev/mii/qsphy.c optional miibus | qsphy dev/mii/rdcphy.c optional miibus | rdcphy dev/mii/rgephy.c optional miibus | rgephy dev/mii/rlphy.c optional miibus | rlphy dev/mii/rlswitch.c optional rlswitch dev/mii/smcphy.c optional miibus | smcphy dev/mii/smscphy.c optional miibus | smscphy dev/mii/tdkphy.c optional miibus | tdkphy dev/mii/tlphy.c optional miibus | tlphy dev/mii/truephy.c optional miibus | truephy dev/mii/ukphy.c optional miibus | mii dev/mii/ukphy_subr.c optional miibus | mii dev/mii/vscphy.c optional miibus | vscphy dev/mii/xmphy.c optional miibus | xmphy dev/mk48txx/mk48txx.c optional mk48txx dev/mlx/mlx.c optional mlx dev/mlx/mlx_disk.c optional mlx dev/mlx/mlx_pci.c optional mlx pci dev/mly/mly.c optional mly dev/mmc/mmc_subr.c optional mmc | mmcsd !mmccam dev/mmc/mmc.c optional mmc !mmccam dev/mmc/mmcbr_if.m standard dev/mmc/mmcbus_if.m standard dev/mmc/mmcsd.c optional mmcsd !mmccam dev/mmcnull/mmcnull.c optional mmcnull dev/mn/if_mn.c optional mn pci dev/mpr/mpr.c optional mpr dev/mpr/mpr_config.c optional mpr # XXX Work around clang warning, until maintainer approves fix. dev/mpr/mpr_mapping.c optional mpr \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/mpr/mpr_pci.c optional mpr pci dev/mpr/mpr_sas.c optional mpr \ compile-with "${NORMAL_C} ${NO_WUNNEEDED_INTERNAL_DECL}" dev/mpr/mpr_sas_lsi.c optional mpr dev/mpr/mpr_table.c optional mpr dev/mpr/mpr_user.c optional mpr dev/mps/mps.c optional mps dev/mps/mps_config.c optional mps # XXX Work around clang warning, until maintainer approves fix. dev/mps/mps_mapping.c optional mps \ compile-with "${NORMAL_C} ${NO_WSOMETIMES_UNINITIALIZED}" dev/mps/mps_pci.c optional mps pci dev/mps/mps_sas.c optional mps \ compile-with "${NORMAL_C} ${NO_WUNNEEDED_INTERNAL_DECL}" dev/mps/mps_sas_lsi.c optional mps dev/mps/mps_table.c optional mps dev/mps/mps_user.c optional mps dev/mpt/mpt.c optional mpt dev/mpt/mpt_cam.c optional mpt dev/mpt/mpt_debug.c optional mpt dev/mpt/mpt_pci.c optional mpt pci dev/mpt/mpt_raid.c optional mpt dev/mpt/mpt_user.c optional mpt dev/mrsas/mrsas.c optional mrsas dev/mrsas/mrsas_cam.c optional mrsas dev/mrsas/mrsas_ioctl.c optional mrsas dev/mrsas/mrsas_fp.c optional mrsas dev/msk/if_msk.c optional msk dev/mvs/mvs.c optional mvs dev/mvs/mvs_if.m optional mvs dev/mvs/mvs_pci.c optional mvs pci dev/mwl/if_mwl.c optional mwl dev/mwl/if_mwl_pci.c optional mwl pci dev/mwl/mwlhal.c optional mwl mwlfw.c optional mwlfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk mw88W8363.fw:mw88W8363fw mwlboot.fw:mwlboot -mmwl -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "mwlfw.c" mw88W8363.fwo optional mwlfw \ dependency "mw88W8363.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "mw88W8363.fwo" mw88W8363.fw optional mwlfw \ dependency "$S/contrib/dev/mwl/mw88W8363.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "mw88W8363.fw" mwlboot.fwo optional mwlfw \ dependency "mwlboot.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "mwlboot.fwo" mwlboot.fw optional mwlfw \ dependency "$S/contrib/dev/mwl/mwlboot.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "mwlboot.fw" dev/mxge/if_mxge.c optional mxge pci dev/mxge/mxge_eth_z8e.c optional mxge pci dev/mxge/mxge_ethp_z8e.c optional mxge pci dev/mxge/mxge_rss_eth_z8e.c optional mxge pci dev/mxge/mxge_rss_ethp_z8e.c optional mxge pci dev/my/if_my.c optional my dev/nand/nand.c optional nand dev/nand/nand_bbt.c optional nand dev/nand/nand_cdev.c optional nand dev/nand/nand_generic.c optional nand dev/nand/nand_geom.c optional nand dev/nand/nand_id.c optional nand dev/nand/nandbus.c optional nand dev/nand/nandbus_if.m optional nand dev/nand/nand_if.m optional nand dev/nand/nandsim.c optional nandsim nand dev/nand/nandsim_chip.c optional nandsim nand dev/nand/nandsim_ctrl.c optional nandsim nand dev/nand/nandsim_log.c optional nandsim nand dev/nand/nandsim_swap.c optional nandsim nand dev/nand/nfc_if.m optional nand dev/ncr/ncr.c optional ncr pci dev/ncv/ncr53c500.c optional ncv dev/ncv/ncr53c500_pccard.c optional ncv pccard dev/netmap/if_ptnet.c optional netmap inet dev/netmap/netmap.c optional netmap dev/netmap/netmap_freebsd.c optional netmap dev/netmap/netmap_generic.c optional netmap dev/netmap/netmap_mbq.c optional netmap dev/netmap/netmap_mem2.c optional netmap dev/netmap/netmap_monitor.c optional netmap dev/netmap/netmap_offloadings.c optional netmap dev/netmap/netmap_pipe.c optional netmap dev/netmap/netmap_pt.c optional netmap dev/netmap/netmap_vale.c optional netmap # compile-with "${NORMAL_C} -Wconversion -Wextra" dev/nfsmb/nfsmb.c optional nfsmb pci dev/nge/if_nge.c optional nge dev/nxge/if_nxge.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-device.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-mm.c optional nxge dev/nxge/xgehal/xge-queue.c optional nxge dev/nxge/xgehal/xgehal-driver.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-ring.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-channel.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-fifo.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-stats.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nxge/xgehal/xgehal-config.c optional nxge dev/nxge/xgehal/xgehal-mgmt.c optional nxge \ compile-with "${NORMAL_C} ${NO_WSELF_ASSIGN}" dev/nmdm/nmdm.c optional nmdm dev/nsp/nsp.c optional nsp dev/nsp/nsp_pccard.c optional nsp pccard dev/null/null.c standard dev/oce/oce_hw.c optional oce pci dev/oce/oce_if.c optional oce pci dev/oce/oce_mbox.c optional oce pci dev/oce/oce_queue.c optional oce pci dev/oce/oce_sysctl.c optional oce pci dev/oce/oce_util.c optional oce pci dev/ofw/ofw_bus_if.m optional fdt dev/ofw/ofw_bus_subr.c optional fdt dev/ofw/ofw_cpu.c optional fdt dev/ofw/ofw_fdt.c optional fdt dev/ofw/ofw_if.m optional fdt dev/ofw/ofw_subr.c optional fdt dev/ofw/ofwbus.c optional fdt dev/ofw/openfirm.c optional fdt dev/ofw/openfirmio.c optional fdt dev/ow/ow.c optional ow \ dependency "owll_if.h" \ dependency "own_if.h" dev/ow/owll_if.m optional ow dev/ow/own_if.m optional ow dev/ow/ow_temp.c optional ow_temp dev/ow/owc_gpiobus.c optional owc gpio dev/pbio/pbio.c optional pbio isa dev/pccard/card_if.m standard dev/pccard/pccard.c optional pccard dev/pccard/pccard_cis.c optional pccard dev/pccard/pccard_cis_quirks.c optional pccard dev/pccard/pccard_device.c optional pccard dev/pccard/power_if.m standard dev/pccbb/pccbb.c optional cbb dev/pccbb/pccbb_isa.c optional cbb isa dev/pccbb/pccbb_pci.c optional cbb pci dev/pcf/pcf.c optional pcf dev/pci/fixup_pci.c optional pci dev/pci/hostb_pci.c optional pci dev/pci/ignore_pci.c optional pci dev/pci/isa_pci.c optional pci isa dev/pci/pci.c optional pci dev/pci/pci_if.m standard dev/pci/pci_iov.c optional pci pci_iov dev/pci/pci_iov_if.m standard dev/pci/pci_iov_schema.c optional pci pci_iov dev/pci/pci_pci.c optional pci dev/pci/pci_subr.c optional pci dev/pci/pci_user.c optional pci dev/pci/pcib_if.m standard dev/pci/pcib_support.c standard dev/pci/vga_pci.c optional pci dev/pcn/if_pcn.c optional pcn pci dev/pdq/if_fpa.c optional fpa pci dev/pdq/pdq.c optional nowerror fpa pci dev/pdq/pdq_ifsubr.c optional nowerror fpa pci dev/pms/freebsd/driver/ini/src/agtiapi.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sadisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/mpi.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/saframe.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sahw.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sainit.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/saint.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sampicmd.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sampirsp.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/saphy.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/saport.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sasata.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sasmp.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sassp.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/satimer.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/sautil.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/saioctlcmd.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sallsdk/spc/mpidebug.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dminit.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dmsmp.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dmdisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dmport.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dmtimer.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/discovery/dm/dmmisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/sminit.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/smmisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/smsat.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/smsatcb.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/smsathw.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/sat/src/smtimer.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdinit.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdmisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdesgl.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdport.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdint.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdioctl.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdhw.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/ossacmnapi.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tddmcmnapi.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdsmcmnapi.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/common/tdtimers.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sas/ini/itdio.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sas/ini/itdcb.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sas/ini/itdinit.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sas/ini/itddisc.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sata/host/sat.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sata/host/ossasat.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/pms/RefTisa/tisa/sassata/sata/host/sathw.c optional pmspcv \ compile-with "${NORMAL_C} -Wunused-variable -Woverflow -Wparentheses -w" dev/ppbus/if_plip.c optional plip dev/ppbus/immio.c optional vpo dev/ppbus/lpbb.c optional lpbb dev/ppbus/lpt.c optional lpt dev/ppbus/pcfclock.c optional pcfclock dev/ppbus/ppb_1284.c optional ppbus dev/ppbus/ppb_base.c optional ppbus dev/ppbus/ppb_msq.c optional ppbus dev/ppbus/ppbconf.c optional ppbus dev/ppbus/ppbus_if.m optional ppbus dev/ppbus/ppi.c optional ppi dev/ppbus/pps.c optional pps dev/ppbus/vpo.c optional vpo dev/ppbus/vpoio.c optional vpo dev/ppc/ppc.c optional ppc dev/ppc/ppc_acpi.c optional ppc acpi dev/ppc/ppc_isa.c optional ppc isa dev/ppc/ppc_pci.c optional ppc pci dev/ppc/ppc_puc.c optional ppc puc dev/proto/proto_bus_isa.c optional proto acpi | proto isa dev/proto/proto_bus_pci.c optional proto pci dev/proto/proto_busdma.c optional proto dev/proto/proto_core.c optional proto dev/pst/pst-iop.c optional pst dev/pst/pst-pci.c optional pst pci dev/pst/pst-raid.c optional pst dev/pty/pty.c optional pty dev/puc/puc.c optional puc dev/puc/puc_cfg.c optional puc dev/puc/puc_pccard.c optional puc pccard dev/puc/puc_pci.c optional puc pci dev/puc/pucdata.c optional puc pci dev/quicc/quicc_core.c optional quicc dev/ral/rt2560.c optional ral dev/ral/rt2661.c optional ral dev/ral/rt2860.c optional ral dev/ral/if_ral_pci.c optional ral pci rt2561fw.c optional rt2561fw | ralfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rt2561.fw:rt2561fw -mrt2561 -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rt2561fw.c" rt2561fw.fwo optional rt2561fw | ralfw \ dependency "rt2561.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rt2561fw.fwo" rt2561.fw optional rt2561fw | ralfw \ dependency "$S/contrib/dev/ral/rt2561.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rt2561.fw" rt2561sfw.c optional rt2561sfw | ralfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rt2561s.fw:rt2561sfw -mrt2561s -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rt2561sfw.c" rt2561sfw.fwo optional rt2561sfw | ralfw \ dependency "rt2561s.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rt2561sfw.fwo" rt2561s.fw optional rt2561sfw | ralfw \ dependency "$S/contrib/dev/ral/rt2561s.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rt2561s.fw" rt2661fw.c optional rt2661fw | ralfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rt2661.fw:rt2661fw -mrt2661 -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rt2661fw.c" rt2661fw.fwo optional rt2661fw | ralfw \ dependency "rt2661.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rt2661fw.fwo" rt2661.fw optional rt2661fw | ralfw \ dependency "$S/contrib/dev/ral/rt2661.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rt2661.fw" rt2860fw.c optional rt2860fw | ralfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rt2860.fw:rt2860fw -mrt2860 -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rt2860fw.c" rt2860fw.fwo optional rt2860fw | ralfw \ dependency "rt2860.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rt2860fw.fwo" rt2860.fw optional rt2860fw | ralfw \ dependency "$S/contrib/dev/ral/rt2860.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rt2860.fw" dev/random/random_infra.c optional random dev/random/random_harvestq.c optional random dev/random/randomdev.c optional random random_yarrow | \ random !random_yarrow !random_loadable dev/random/yarrow.c optional random random_yarrow dev/random/fortuna.c optional random !random_yarrow !random_loadable dev/random/hash.c optional random random_yarrow | \ random !random_yarrow !random_loadable dev/rc/rc.c optional rc dev/rccgpio/rccgpio.c optional rccgpio gpio dev/re/if_re.c optional re dev/rl/if_rl.c optional rl pci dev/rndtest/rndtest.c optional rndtest dev/rp/rp.c optional rp dev/rp/rp_isa.c optional rp isa dev/rp/rp_pci.c optional rp pci # dev/rtwn/if_rtwn.c optional rtwn dev/rtwn/if_rtwn_beacon.c optional rtwn dev/rtwn/if_rtwn_calib.c optional rtwn dev/rtwn/if_rtwn_cam.c optional rtwn dev/rtwn/if_rtwn_efuse.c optional rtwn dev/rtwn/if_rtwn_fw.c optional rtwn dev/rtwn/if_rtwn_rx.c optional rtwn dev/rtwn/if_rtwn_task.c optional rtwn dev/rtwn/if_rtwn_tx.c optional rtwn # dev/rtwn/pci/rtwn_pci_attach.c optional rtwn_pci pci dev/rtwn/pci/rtwn_pci_reg.c optional rtwn_pci pci dev/rtwn/pci/rtwn_pci_rx.c optional rtwn_pci pci dev/rtwn/pci/rtwn_pci_tx.c optional rtwn_pci pci # dev/rtwn/usb/rtwn_usb_attach.c optional rtwn_usb dev/rtwn/usb/rtwn_usb_ep.c optional rtwn_usb dev/rtwn/usb/rtwn_usb_reg.c optional rtwn_usb dev/rtwn/usb/rtwn_usb_rx.c optional rtwn_usb dev/rtwn/usb/rtwn_usb_tx.c optional rtwn_usb # RTL8188E dev/rtwn/rtl8188e/r88e_beacon.c optional rtwn dev/rtwn/rtl8188e/r88e_calib.c optional rtwn dev/rtwn/rtl8188e/r88e_chan.c optional rtwn dev/rtwn/rtl8188e/r88e_fw.c optional rtwn dev/rtwn/rtl8188e/r88e_init.c optional rtwn dev/rtwn/rtl8188e/r88e_led.c optional rtwn dev/rtwn/rtl8188e/r88e_tx.c optional rtwn dev/rtwn/rtl8188e/r88e_rf.c optional rtwn dev/rtwn/rtl8188e/r88e_rom.c optional rtwn dev/rtwn/rtl8188e/r88e_rx.c optional rtwn dev/rtwn/rtl8188e/usb/r88eu_attach.c optional rtwn_usb dev/rtwn/rtl8188e/usb/r88eu_init.c optional rtwn_usb dev/rtwn/rtl8188e/usb/r88eu_rx.c optional rtwn_usb # RTL8192C dev/rtwn/rtl8192c/r92c_attach.c optional rtwn dev/rtwn/rtl8192c/r92c_beacon.c optional rtwn dev/rtwn/rtl8192c/r92c_calib.c optional rtwn dev/rtwn/rtl8192c/r92c_chan.c optional rtwn dev/rtwn/rtl8192c/r92c_fw.c optional rtwn dev/rtwn/rtl8192c/r92c_init.c optional rtwn dev/rtwn/rtl8192c/r92c_llt.c optional rtwn dev/rtwn/rtl8192c/r92c_rf.c optional rtwn dev/rtwn/rtl8192c/r92c_rom.c optional rtwn dev/rtwn/rtl8192c/r92c_rx.c optional rtwn dev/rtwn/rtl8192c/r92c_tx.c optional rtwn dev/rtwn/rtl8192c/pci/r92ce_attach.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_calib.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_fw.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_init.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_led.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_rx.c optional rtwn_pci pci dev/rtwn/rtl8192c/pci/r92ce_tx.c optional rtwn_pci pci dev/rtwn/rtl8192c/usb/r92cu_attach.c optional rtwn_usb dev/rtwn/rtl8192c/usb/r92cu_init.c optional rtwn_usb dev/rtwn/rtl8192c/usb/r92cu_led.c optional rtwn_usb dev/rtwn/rtl8192c/usb/r92cu_rx.c optional rtwn_usb dev/rtwn/rtl8192c/usb/r92cu_tx.c optional rtwn_usb # RTL8192E dev/rtwn/rtl8192e/r92e_chan.c optional rtwn dev/rtwn/rtl8192e/r92e_fw.c optional rtwn dev/rtwn/rtl8192e/r92e_init.c optional rtwn dev/rtwn/rtl8192e/r92e_led.c optional rtwn dev/rtwn/rtl8192e/r92e_rf.c optional rtwn dev/rtwn/rtl8192e/r92e_rom.c optional rtwn dev/rtwn/rtl8192e/r92e_rx.c optional rtwn dev/rtwn/rtl8192e/usb/r92eu_attach.c optional rtwn_usb dev/rtwn/rtl8192e/usb/r92eu_init.c optional rtwn_usb # RTL8812A dev/rtwn/rtl8812a/r12a_beacon.c optional rtwn dev/rtwn/rtl8812a/r12a_calib.c optional rtwn dev/rtwn/rtl8812a/r12a_caps.c optional rtwn dev/rtwn/rtl8812a/r12a_chan.c optional rtwn dev/rtwn/rtl8812a/r12a_fw.c optional rtwn dev/rtwn/rtl8812a/r12a_init.c optional rtwn dev/rtwn/rtl8812a/r12a_led.c optional rtwn dev/rtwn/rtl8812a/r12a_rf.c optional rtwn dev/rtwn/rtl8812a/r12a_rom.c optional rtwn dev/rtwn/rtl8812a/r12a_rx.c optional rtwn dev/rtwn/rtl8812a/r12a_tx.c optional rtwn dev/rtwn/rtl8812a/usb/r12au_attach.c optional rtwn_usb dev/rtwn/rtl8812a/usb/r12au_init.c optional rtwn_usb dev/rtwn/rtl8812a/usb/r12au_rx.c optional rtwn_usb dev/rtwn/rtl8812a/usb/r12au_tx.c optional rtwn_usb # RTL8821A dev/rtwn/rtl8821a/r21a_beacon.c optional rtwn dev/rtwn/rtl8821a/r21a_calib.c optional rtwn dev/rtwn/rtl8821a/r21a_chan.c optional rtwn dev/rtwn/rtl8821a/r21a_fw.c optional rtwn dev/rtwn/rtl8821a/r21a_init.c optional rtwn dev/rtwn/rtl8821a/r21a_led.c optional rtwn dev/rtwn/rtl8821a/r21a_rom.c optional rtwn dev/rtwn/rtl8821a/r21a_rx.c optional rtwn dev/rtwn/rtl8821a/usb/r21au_attach.c optional rtwn_usb dev/rtwn/rtl8821a/usb/r21au_dfs.c optional rtwn_usb dev/rtwn/rtl8821a/usb/r21au_init.c optional rtwn_usb rtwn-rtl8188eufw.c optional rtwn-rtl8188eufw | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8188eufw.fw:rtwn-rtl8188eufw:111 -mrtwn-rtl8188eufw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8188eufw.c" rtwn-rtl8188eufw.fwo optional rtwn-rtl8188eufw | rtwnfw \ dependency "rtwn-rtl8188eufw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8188eufw.fwo" rtwn-rtl8188eufw.fw optional rtwn-rtl8188eufw | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8188eufw.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8188eufw.fw" rtwn-rtl8192cfwE.c optional rtwn-rtl8192cfwE | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE.fw:rtwn-rtl8192cfwE:111 -mrtwn-rtl8192cfwE -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8192cfwE.c" rtwn-rtl8192cfwE.fwo optional rtwn-rtl8192cfwE | rtwnfw \ dependency "rtwn-rtl8192cfwE.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8192cfwE.fwo" rtwn-rtl8192cfwE.fw optional rtwn-rtl8192cfwE | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwE.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8192cfwE.fw" rtwn-rtl8192cfwE_B.c optional rtwn-rtl8192cfwE_B | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwE_B.fw:rtwn-rtl8192cfwE_B:111 -mrtwn-rtl8192cfwE_B -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8192cfwE_B.c" rtwn-rtl8192cfwE_B.fwo optional rtwn-rtl8192cfwE_B | rtwnfw \ dependency "rtwn-rtl8192cfwE_B.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8192cfwE_B.fwo" rtwn-rtl8192cfwE_B.fw optional rtwn-rtl8192cfwE_B | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwE_B.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8192cfwE_B.fw" rtwn-rtl8192cfwT.c optional rtwn-rtl8192cfwT | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwT.fw:rtwn-rtl8192cfwT:111 -mrtwn-rtl8192cfwT -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8192cfwT.c" rtwn-rtl8192cfwT.fwo optional rtwn-rtl8192cfwT | rtwnfw \ dependency "rtwn-rtl8192cfwT.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8192cfwT.fwo" rtwn-rtl8192cfwT.fw optional rtwn-rtl8192cfwT | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwT.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8192cfwT.fw" rtwn-rtl8192cfwU.c optional rtwn-rtl8192cfwU | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192cfwU.fw:rtwn-rtl8192cfwU:111 -mrtwn-rtl8192cfwU -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8192cfwU.c" rtwn-rtl8192cfwU.fwo optional rtwn-rtl8192cfwU | rtwnfw \ dependency "rtwn-rtl8192cfwU.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8192cfwU.fwo" rtwn-rtl8192cfwU.fw optional rtwn-rtl8192cfwU | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8192cfwU.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8192cfwU.fw" rtwn-rtl8192eufw.c optional rtwn-rtl8192eufw | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8192eufw.fw:rtwn-rtl8192eufw:111 -mrtwn-rtl8192eufw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8192eufw.c" rtwn-rtl8192eufw.fwo optional rtwn-rtl8192eufw | rtwnfw \ dependency "rtwn-rtl8192eufw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8192eufw.fwo" rtwn-rtl8192eufw.fw optional rtwn-rtl8192eufw | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8192eufw.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8192eufw.fw" rtwn-rtl8812aufw.c optional rtwn-rtl8812aufw | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8812aufw.fw:rtwn-rtl8812aufw:111 -mrtwn-rtl8812aufw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8812aufw.c" rtwn-rtl8812aufw.fwo optional rtwn-rtl8812aufw | rtwnfw \ dependency "rtwn-rtl8812aufw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8812aufw.fwo" rtwn-rtl8812aufw.fw optional rtwn-rtl8812aufw | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8812aufw.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8812aufw.fw" rtwn-rtl8821aufw.c optional rtwn-rtl8821aufw | rtwnfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rtwn-rtl8821aufw.fw:rtwn-rtl8821aufw:111 -mrtwn-rtl8821aufw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rtwn-rtl8821aufw.c" rtwn-rtl8821aufw.fwo optional rtwn-rtl8821aufw | rtwnfw \ dependency "rtwn-rtl8821aufw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rtwn-rtl8821aufw.fwo" rtwn-rtl8821aufw.fw optional rtwn-rtl8821aufw | rtwnfw \ dependency "$S/contrib/dev/rtwn/rtwn-rtl8821aufw.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rtwn-rtl8821aufw.fw" dev/safe/safe.c optional safe dev/scc/scc_if.m optional scc dev/scc/scc_bfe_ebus.c optional scc ebus dev/scc/scc_bfe_quicc.c optional scc quicc dev/scc/scc_bfe_sbus.c optional scc fhc | scc sbus dev/scc/scc_core.c optional scc dev/scc/scc_dev_quicc.c optional scc quicc dev/scc/scc_dev_sab82532.c optional scc dev/scc/scc_dev_z8530.c optional scc dev/sdhci/sdhci.c optional sdhci dev/sdhci/sdhci_fdt_gpio.c optional sdhci fdt gpio dev/sdhci/sdhci_if.m optional sdhci dev/sdhci/sdhci_acpi.c optional sdhci acpi dev/sdhci/sdhci_pci.c optional sdhci pci dev/sf/if_sf.c optional sf pci dev/sge/if_sge.c optional sge pci dev/siba/siba_bwn.c optional siba_bwn pci dev/siba/siba_core.c optional siba_bwn pci dev/siis/siis.c optional siis pci dev/sis/if_sis.c optional sis pci dev/sk/if_sk.c optional sk pci dev/smbus/smb.c optional smb dev/smbus/smbconf.c optional smbus dev/smbus/smbus.c optional smbus dev/smbus/smbus_if.m optional smbus dev/smc/if_smc.c optional smc dev/smc/if_smc_fdt.c optional smc fdt dev/sn/if_sn.c optional sn dev/sn/if_sn_isa.c optional sn isa dev/sn/if_sn_pccard.c optional sn pccard dev/snp/snp.c optional snp dev/sound/clone.c optional sound dev/sound/unit.c optional sound dev/sound/isa/ad1816.c optional snd_ad1816 isa dev/sound/isa/ess.c optional snd_ess isa dev/sound/isa/gusc.c optional snd_gusc isa dev/sound/isa/mss.c optional snd_mss isa dev/sound/isa/sb16.c optional snd_sb16 isa dev/sound/isa/sb8.c optional snd_sb8 isa dev/sound/isa/sbc.c optional snd_sbc isa dev/sound/isa/sndbuf_dma.c optional sound isa dev/sound/pci/als4000.c optional snd_als4000 pci dev/sound/pci/atiixp.c optional snd_atiixp pci dev/sound/pci/cmi.c optional snd_cmi pci dev/sound/pci/cs4281.c optional snd_cs4281 pci dev/sound/pci/csa.c optional snd_csa pci dev/sound/pci/csapcm.c optional snd_csa pci dev/sound/pci/ds1.c optional snd_ds1 pci dev/sound/pci/emu10k1.c optional snd_emu10k1 pci dev/sound/pci/emu10kx.c optional snd_emu10kx pci dev/sound/pci/emu10kx-pcm.c optional snd_emu10kx pci dev/sound/pci/emu10kx-midi.c optional snd_emu10kx pci dev/sound/pci/envy24.c optional snd_envy24 pci dev/sound/pci/envy24ht.c optional snd_envy24ht pci dev/sound/pci/es137x.c optional snd_es137x pci dev/sound/pci/fm801.c optional snd_fm801 pci dev/sound/pci/ich.c optional snd_ich pci dev/sound/pci/maestro.c optional snd_maestro pci dev/sound/pci/maestro3.c optional snd_maestro3 pci dev/sound/pci/neomagic.c optional snd_neomagic pci dev/sound/pci/solo.c optional snd_solo pci dev/sound/pci/spicds.c optional snd_spicds pci dev/sound/pci/t4dwave.c optional snd_t4dwave pci dev/sound/pci/via8233.c optional snd_via8233 pci dev/sound/pci/via82c686.c optional snd_via82c686 pci dev/sound/pci/vibes.c optional snd_vibes pci dev/sound/pci/hda/hdaa.c optional snd_hda pci dev/sound/pci/hda/hdaa_patches.c optional snd_hda pci dev/sound/pci/hda/hdac.c optional snd_hda pci dev/sound/pci/hda/hdac_if.m optional snd_hda pci dev/sound/pci/hda/hdacc.c optional snd_hda pci dev/sound/pci/hdspe.c optional snd_hdspe pci dev/sound/pci/hdspe-pcm.c optional snd_hdspe pci dev/sound/pcm/ac97.c optional sound dev/sound/pcm/ac97_if.m optional sound dev/sound/pcm/ac97_patch.c optional sound dev/sound/pcm/buffer.c optional sound \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/channel.c optional sound dev/sound/pcm/channel_if.m optional sound dev/sound/pcm/dsp.c optional sound dev/sound/pcm/feeder.c optional sound dev/sound/pcm/feeder_chain.c optional sound dev/sound/pcm/feeder_eq.c optional sound \ dependency "feeder_eq_gen.h" \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/feeder_if.m optional sound dev/sound/pcm/feeder_format.c optional sound \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/feeder_matrix.c optional sound \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/feeder_mixer.c optional sound \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/feeder_rate.c optional sound \ dependency "feeder_rate_gen.h" \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/feeder_volume.c optional sound \ dependency "snd_fxdiv_gen.h" dev/sound/pcm/mixer.c optional sound dev/sound/pcm/mixer_if.m optional sound dev/sound/pcm/sndstat.c optional sound dev/sound/pcm/sound.c optional sound dev/sound/pcm/vchan.c optional sound dev/sound/usb/uaudio.c optional snd_uaudio usb dev/sound/usb/uaudio_pcm.c optional snd_uaudio usb dev/sound/midi/midi.c optional sound dev/sound/midi/mpu401.c optional sound dev/sound/midi/mpu_if.m optional sound dev/sound/midi/mpufoi_if.m optional sound dev/sound/midi/sequencer.c optional sound dev/sound/midi/synth_if.m optional sound dev/spibus/ofw_spibus.c optional fdt spibus dev/spibus/spibus.c optional spibus \ dependency "spibus_if.h" dev/spibus/spigen.c optional spigen dev/spibus/spibus_if.m optional spibus dev/ste/if_ste.c optional ste pci dev/stg/tmc18c30.c optional stg dev/stg/tmc18c30_isa.c optional stg isa dev/stg/tmc18c30_pccard.c optional stg pccard dev/stg/tmc18c30_pci.c optional stg pci dev/stg/tmc18c30_subr.c optional stg dev/stge/if_stge.c optional stge dev/sym/sym_hipd.c optional sym \ dependency "$S/dev/sym/sym_{conf,defs}.h" dev/syscons/blank/blank_saver.c optional blank_saver dev/syscons/daemon/daemon_saver.c optional daemon_saver dev/syscons/dragon/dragon_saver.c optional dragon_saver dev/syscons/fade/fade_saver.c optional fade_saver dev/syscons/fire/fire_saver.c optional fire_saver dev/syscons/green/green_saver.c optional green_saver dev/syscons/logo/logo.c optional logo_saver dev/syscons/logo/logo_saver.c optional logo_saver dev/syscons/rain/rain_saver.c optional rain_saver dev/syscons/schistory.c optional sc dev/syscons/scmouse.c optional sc dev/syscons/scterm.c optional sc dev/syscons/scvidctl.c optional sc dev/syscons/snake/snake_saver.c optional snake_saver dev/syscons/star/star_saver.c optional star_saver dev/syscons/syscons.c optional sc dev/syscons/sysmouse.c optional sc dev/syscons/warp/warp_saver.c optional warp_saver dev/tdfx/tdfx_linux.c optional tdfx_linux tdfx compat_linux dev/tdfx/tdfx_pci.c optional tdfx pci dev/ti/if_ti.c optional ti pci dev/tl/if_tl.c optional tl pci dev/trm/trm.c optional trm dev/twa/tw_cl_init.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_intr.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_io.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_cl_misc.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_cam.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twa/tw_osl_freebsd.c optional twa \ compile-with "${NORMAL_C} -I$S/dev/twa" dev/twe/twe.c optional twe dev/twe/twe_freebsd.c optional twe dev/tws/tws.c optional tws dev/tws/tws_cam.c optional tws dev/tws/tws_hdm.c optional tws dev/tws/tws_services.c optional tws dev/tws/tws_user.c optional tws dev/tx/if_tx.c optional tx dev/txp/if_txp.c optional txp dev/uart/uart_bus_acpi.c optional uart acpi dev/uart/uart_bus_ebus.c optional uart ebus dev/uart/uart_bus_fdt.c optional uart fdt dev/uart/uart_bus_isa.c optional uart isa dev/uart/uart_bus_pccard.c optional uart pccard dev/uart/uart_bus_pci.c optional uart pci dev/uart/uart_bus_puc.c optional uart puc dev/uart/uart_bus_scc.c optional uart scc dev/uart/uart_core.c optional uart dev/uart/uart_dbg.c optional uart gdb dev/uart/uart_dev_ns8250.c optional uart uart_ns8250 | uart uart_snps dev/uart/uart_dev_pl011.c optional uart pl011 dev/uart/uart_dev_quicc.c optional uart quicc dev/uart/uart_dev_sab82532.c optional uart uart_sab82532 dev/uart/uart_dev_sab82532.c optional uart scc dev/uart/uart_dev_snps.c optional uart uart_snps fdt dev/uart/uart_dev_z8530.c optional uart uart_z8530 dev/uart/uart_dev_z8530.c optional uart scc dev/uart/uart_if.m optional uart dev/uart/uart_subr.c optional uart dev/uart/uart_tty.c optional uart dev/ubsec/ubsec.c optional ubsec # # USB controller drivers # dev/usb/controller/at91dci.c optional at91dci dev/usb/controller/at91dci_atmelarm.c optional at91dci at91rm9200 dev/usb/controller/musb_otg.c optional musb dev/usb/controller/musb_otg_atmelarm.c optional musb at91rm9200 dev/usb/controller/dwc_otg.c optional dwcotg dev/usb/controller/dwc_otg_fdt.c optional dwcotg fdt dev/usb/controller/ehci.c optional ehci dev/usb/controller/ehci_pci.c optional ehci pci dev/usb/controller/ohci.c optional ohci dev/usb/controller/ohci_pci.c optional ohci pci dev/usb/controller/uhci.c optional uhci dev/usb/controller/uhci_pci.c optional uhci pci dev/usb/controller/xhci.c optional xhci dev/usb/controller/xhci_pci.c optional xhci pci dev/usb/controller/saf1761_otg.c optional saf1761otg dev/usb/controller/saf1761_otg_fdt.c optional saf1761otg fdt dev/usb/controller/uss820dci.c optional uss820dci dev/usb/controller/uss820dci_atmelarm.c optional uss820dci at91rm9200 dev/usb/controller/usb_controller.c optional usb # # USB storage drivers # dev/usb/storage/cfumass.c optional cfumass ctl dev/usb/storage/umass.c optional umass dev/usb/storage/urio.c optional urio dev/usb/storage/ustorage_fs.c optional usfs # # USB core # dev/usb/usb_busdma.c optional usb dev/usb/usb_core.c optional usb dev/usb/usb_debug.c optional usb dev/usb/usb_dev.c optional usb dev/usb/usb_device.c optional usb dev/usb/usb_dynamic.c optional usb dev/usb/usb_error.c optional usb dev/usb/usb_generic.c optional usb dev/usb/usb_handle_request.c optional usb dev/usb/usb_hid.c optional usb dev/usb/usb_hub.c optional usb dev/usb/usb_if.m optional usb dev/usb/usb_lookup.c optional usb dev/usb/usb_mbuf.c optional usb dev/usb/usb_msctest.c optional usb dev/usb/usb_parse.c optional usb dev/usb/usb_pf.c optional usb dev/usb/usb_process.c optional usb dev/usb/usb_request.c optional usb dev/usb/usb_transfer.c optional usb dev/usb/usb_util.c optional usb # # USB network drivers # dev/usb/net/if_aue.c optional aue dev/usb/net/if_axe.c optional axe dev/usb/net/if_axge.c optional axge dev/usb/net/if_cdce.c optional cdce dev/usb/net/if_cue.c optional cue dev/usb/net/if_ipheth.c optional ipheth dev/usb/net/if_kue.c optional kue dev/usb/net/if_mos.c optional mos dev/usb/net/if_rue.c optional rue dev/usb/net/if_smsc.c optional smsc dev/usb/net/if_udav.c optional udav dev/usb/net/if_ure.c optional ure dev/usb/net/if_usie.c optional usie dev/usb/net/if_urndis.c optional urndis dev/usb/net/ruephy.c optional rue dev/usb/net/usb_ethernet.c optional uether | aue | axe | axge | cdce | \ cue | ipheth | kue | mos | rue | \ smsc | udav | ure | urndis dev/usb/net/uhso.c optional uhso # # USB WLAN drivers # dev/usb/wlan/if_rsu.c optional rsu rsu-rtl8712fw.c optional rsu-rtl8712fw | rsufw \ compile-with "${AWK} -f $S/tools/fw_stub.awk rsu-rtl8712fw.fw:rsu-rtl8712fw:120 -mrsu-rtl8712fw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "rsu-rtl8712fw.c" rsu-rtl8712fw.fwo optional rsu-rtl8712fw | rsufw \ dependency "rsu-rtl8712fw.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "rsu-rtl8712fw.fwo" rsu-rtl8712fw.fw optional rsu-rtl8712.fw | rsufw \ dependency "$S/contrib/dev/rsu/rsu-rtl8712fw.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "rsu-rtl8712fw.fw" dev/usb/wlan/if_rum.c optional rum dev/usb/wlan/if_run.c optional run runfw.c optional runfw \ compile-with "${AWK} -f $S/tools/fw_stub.awk run.fw:runfw -mrunfw -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "runfw.c" runfw.fwo optional runfw \ dependency "run.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "runfw.fwo" run.fw optional runfw \ dependency "$S/contrib/dev/run/rt2870.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "run.fw" dev/usb/wlan/if_uath.c optional uath dev/usb/wlan/if_upgt.c optional upgt dev/usb/wlan/if_ural.c optional ural dev/usb/wlan/if_urtw.c optional urtw dev/usb/wlan/if_zyd.c optional zyd # # USB serial and parallel port drivers # dev/usb/serial/u3g.c optional u3g dev/usb/serial/uark.c optional uark dev/usb/serial/ubsa.c optional ubsa dev/usb/serial/ubser.c optional ubser dev/usb/serial/uchcom.c optional uchcom dev/usb/serial/ucycom.c optional ucycom dev/usb/serial/ufoma.c optional ufoma dev/usb/serial/uftdi.c optional uftdi dev/usb/serial/ugensa.c optional ugensa dev/usb/serial/uipaq.c optional uipaq dev/usb/serial/ulpt.c optional ulpt dev/usb/serial/umcs.c optional umcs dev/usb/serial/umct.c optional umct dev/usb/serial/umodem.c optional umodem dev/usb/serial/umoscom.c optional umoscom dev/usb/serial/uplcom.c optional uplcom dev/usb/serial/uslcom.c optional uslcom dev/usb/serial/uvisor.c optional uvisor dev/usb/serial/uvscom.c optional uvscom dev/usb/serial/usb_serial.c optional ucom | u3g | uark | ubsa | ubser | \ uchcom | ucycom | ufoma | uftdi | \ ugensa | uipaq | umcs | umct | \ umodem | umoscom | uplcom | usie | \ uslcom | uvisor | uvscom # # USB misc drivers # dev/usb/misc/ufm.c optional ufm dev/usb/misc/udbp.c optional udbp dev/usb/misc/ugold.c optional ugold dev/usb/misc/uled.c optional uled # # USB input drivers # dev/usb/input/atp.c optional atp dev/usb/input/uep.c optional uep dev/usb/input/uhid.c optional uhid dev/usb/input/ukbd.c optional ukbd dev/usb/input/ums.c optional ums dev/usb/input/wsp.c optional wsp # # USB quirks # dev/usb/quirk/usb_quirk.c optional usb # # USB templates # dev/usb/template/usb_template.c optional usb_template dev/usb/template/usb_template_audio.c optional usb_template dev/usb/template/usb_template_cdce.c optional usb_template dev/usb/template/usb_template_kbd.c optional usb_template dev/usb/template/usb_template_modem.c optional usb_template dev/usb/template/usb_template_mouse.c optional usb_template dev/usb/template/usb_template_msc.c optional usb_template dev/usb/template/usb_template_mtp.c optional usb_template dev/usb/template/usb_template_phone.c optional usb_template dev/usb/template/usb_template_serialnet.c optional usb_template dev/usb/template/usb_template_midi.c optional usb_template # # USB video drivers # dev/usb/video/udl.c optional udl # # USB END # dev/videomode/videomode.c optional videomode dev/videomode/edid.c optional videomode dev/videomode/pickmode.c optional videomode dev/videomode/vesagtf.c optional videomode dev/vge/if_vge.c optional vge dev/viapm/viapm.c optional viapm pci dev/virtio/virtio.c optional virtio dev/virtio/virtqueue.c optional virtio dev/virtio/virtio_bus_if.m optional virtio dev/virtio/virtio_if.m optional virtio dev/virtio/pci/virtio_pci.c optional virtio_pci dev/virtio/mmio/virtio_mmio.c optional virtio_mmio fdt dev/virtio/mmio/virtio_mmio_if.m optional virtio_mmio fdt dev/virtio/network/if_vtnet.c optional vtnet dev/virtio/block/virtio_blk.c optional virtio_blk dev/virtio/balloon/virtio_balloon.c optional virtio_balloon dev/virtio/scsi/virtio_scsi.c optional virtio_scsi dev/virtio/random/virtio_random.c optional virtio_random dev/virtio/console/virtio_console.c optional virtio_console dev/vkbd/vkbd.c optional vkbd dev/vr/if_vr.c optional vr pci dev/vt/colors/vt_termcolors.c optional vt dev/vt/font/vt_font_default.c optional vt dev/vt/font/vt_mouse_cursor.c optional vt dev/vt/hw/efifb/efifb.c optional vt_efifb dev/vt/hw/fb/vt_fb.c optional vt dev/vt/hw/vga/vt_vga.c optional vt vt_vga dev/vt/logo/logo_freebsd.c optional vt splash dev/vt/logo/logo_beastie.c optional vt splash dev/vt/vt_buf.c optional vt dev/vt/vt_consolectl.c optional vt dev/vt/vt_core.c optional vt dev/vt/vt_cpulogos.c optional vt splash dev/vt/vt_font.c optional vt dev/vt/vt_sysmouse.c optional vt dev/vte/if_vte.c optional vte pci dev/vx/if_vx.c optional vx dev/vx/if_vx_pci.c optional vx pci dev/vxge/vxge.c optional vxge dev/vxge/vxgehal/vxgehal-ifmsg.c optional vxge dev/vxge/vxgehal/vxgehal-mrpcim.c optional vxge dev/vxge/vxgehal/vxge-queue.c optional vxge dev/vxge/vxgehal/vxgehal-ring.c optional vxge dev/vxge/vxgehal/vxgehal-swapper.c optional vxge dev/vxge/vxgehal/vxgehal-mgmt.c optional vxge dev/vxge/vxgehal/vxgehal-srpcim.c optional vxge dev/vxge/vxgehal/vxgehal-config.c optional vxge dev/vxge/vxgehal/vxgehal-blockpool.c optional vxge dev/vxge/vxgehal/vxgehal-doorbells.c optional vxge dev/vxge/vxgehal/vxgehal-mgmtaux.c optional vxge dev/vxge/vxgehal/vxgehal-device.c optional vxge dev/vxge/vxgehal/vxgehal-mm.c optional vxge dev/vxge/vxgehal/vxgehal-driver.c optional vxge dev/vxge/vxgehal/vxgehal-virtualpath.c optional vxge dev/vxge/vxgehal/vxgehal-channel.c optional vxge dev/vxge/vxgehal/vxgehal-fifo.c optional vxge dev/watchdog/watchdog.c standard dev/wb/if_wb.c optional wb pci dev/wi/if_wi.c optional wi dev/wi/if_wi_pccard.c optional wi pccard dev/wi/if_wi_pci.c optional wi pci dev/wpi/if_wpi.c optional wpi pci wpifw.c optional wpifw \ compile-with "${AWK} -f $S/tools/fw_stub.awk wpi.fw:wpifw:153229 -mwpi -c${.TARGET}" \ no-implicit-rule before-depend local \ clean "wpifw.c" wpifw.fwo optional wpifw \ dependency "wpi.fw" \ compile-with "${NORMAL_FWO}" \ no-implicit-rule \ clean "wpifw.fwo" wpi.fw optional wpifw \ dependency "$S/contrib/dev/wpi/iwlwifi-3945-15.32.2.9.fw.uu" \ compile-with "${NORMAL_FW}" \ no-obj no-implicit-rule \ clean "wpi.fw" dev/xdma/xdma.c optional xdma dev/xdma/xdma_if.m optional xdma dev/xdma/xdma_fdt_test.c optional xdma xdma_test fdt dev/xe/if_xe.c optional xe dev/xe/if_xe_pccard.c optional xe pccard dev/xen/balloon/balloon.c optional xenhvm dev/xen/blkfront/blkfront.c optional xenhvm dev/xen/blkback/blkback.c optional xenhvm dev/xen/console/xen_console.c optional xenhvm dev/xen/control/control.c optional xenhvm dev/xen/grant_table/grant_table.c optional xenhvm dev/xen/netback/netback.c optional xenhvm dev/xen/netfront/netfront.c optional xenhvm dev/xen/xenpci/xenpci.c optional xenpci dev/xen/timer/timer.c optional xenhvm dev/xen/pvcpu/pvcpu.c optional xenhvm dev/xen/xenstore/xenstore.c optional xenhvm dev/xen/xenstore/xenstore_dev.c optional xenhvm dev/xen/xenstore/xenstored_dev.c optional xenhvm dev/xen/evtchn/evtchn_dev.c optional xenhvm dev/xen/privcmd/privcmd.c optional xenhvm dev/xen/gntdev/gntdev.c optional xenhvm dev/xen/debug/debug.c optional xenhvm dev/xl/if_xl.c optional xl pci dev/xl/xlphy.c optional xl pci fs/autofs/autofs.c optional autofs fs/autofs/autofs_vfsops.c optional autofs fs/autofs/autofs_vnops.c optional autofs fs/deadfs/dead_vnops.c standard fs/devfs/devfs_devs.c standard fs/devfs/devfs_dir.c standard fs/devfs/devfs_rule.c standard fs/devfs/devfs_vfsops.c standard fs/devfs/devfs_vnops.c standard fs/fdescfs/fdesc_vfsops.c optional fdescfs fs/fdescfs/fdesc_vnops.c optional fdescfs fs/fifofs/fifo_vnops.c standard fs/cuse/cuse.c optional cuse fs/fuse/fuse_device.c optional fuse fs/fuse/fuse_file.c optional fuse fs/fuse/fuse_internal.c optional fuse fs/fuse/fuse_io.c optional fuse fs/fuse/fuse_ipc.c optional fuse fs/fuse/fuse_main.c optional fuse fs/fuse/fuse_node.c optional fuse fs/fuse/fuse_vfsops.c optional fuse fs/fuse/fuse_vnops.c optional fuse fs/msdosfs/msdosfs_conv.c optional msdosfs fs/msdosfs/msdosfs_denode.c optional msdosfs fs/msdosfs/msdosfs_fat.c optional msdosfs fs/msdosfs/msdosfs_iconv.c optional msdosfs_iconv fs/msdosfs/msdosfs_lookup.c optional msdosfs fs/msdosfs/msdosfs_vfsops.c optional msdosfs fs/msdosfs/msdosfs_vnops.c optional msdosfs fs/nandfs/bmap.c optional nandfs fs/nandfs/nandfs_alloc.c optional nandfs fs/nandfs/nandfs_bmap.c optional nandfs fs/nandfs/nandfs_buffer.c optional nandfs fs/nandfs/nandfs_cleaner.c optional nandfs fs/nandfs/nandfs_cpfile.c optional nandfs fs/nandfs/nandfs_dat.c optional nandfs fs/nandfs/nandfs_dir.c optional nandfs fs/nandfs/nandfs_ifile.c optional nandfs fs/nandfs/nandfs_segment.c optional nandfs fs/nandfs/nandfs_subr.c optional nandfs fs/nandfs/nandfs_sufile.c optional nandfs fs/nandfs/nandfs_vfsops.c optional nandfs fs/nandfs/nandfs_vnops.c optional nandfs fs/nfs/nfs_commonkrpc.c optional nfscl | nfsd fs/nfs/nfs_commonsubs.c optional nfscl | nfsd fs/nfs/nfs_commonport.c optional nfscl | nfsd fs/nfs/nfs_commonacl.c optional nfscl | nfsd fs/nfsclient/nfs_clcomsubs.c optional nfscl fs/nfsclient/nfs_clsubs.c optional nfscl fs/nfsclient/nfs_clstate.c optional nfscl fs/nfsclient/nfs_clkrpc.c optional nfscl fs/nfsclient/nfs_clrpcops.c optional nfscl fs/nfsclient/nfs_clvnops.c optional nfscl fs/nfsclient/nfs_clnode.c optional nfscl fs/nfsclient/nfs_clvfsops.c optional nfscl fs/nfsclient/nfs_clport.c optional nfscl fs/nfsclient/nfs_clbio.c optional nfscl fs/nfsclient/nfs_clnfsiod.c optional nfscl fs/nfsserver/nfs_fha_new.c optional nfsd inet fs/nfsserver/nfs_nfsdsocket.c optional nfsd inet fs/nfsserver/nfs_nfsdsubs.c optional nfsd inet fs/nfsserver/nfs_nfsdstate.c optional nfsd inet fs/nfsserver/nfs_nfsdkrpc.c optional nfsd inet fs/nfsserver/nfs_nfsdserv.c optional nfsd inet fs/nfsserver/nfs_nfsdport.c optional nfsd inet fs/nfsserver/nfs_nfsdcache.c optional nfsd inet fs/nullfs/null_subr.c optional nullfs fs/nullfs/null_vfsops.c optional nullfs fs/nullfs/null_vnops.c optional nullfs fs/procfs/procfs.c optional procfs fs/procfs/procfs_dbregs.c optional procfs fs/procfs/procfs_fpregs.c optional procfs fs/procfs/procfs_ioctl.c optional procfs fs/procfs/procfs_map.c optional procfs fs/procfs/procfs_mem.c optional procfs fs/procfs/procfs_note.c optional procfs fs/procfs/procfs_osrel.c optional procfs fs/procfs/procfs_regs.c optional procfs fs/procfs/procfs_rlimit.c optional procfs fs/procfs/procfs_status.c optional procfs fs/procfs/procfs_type.c optional procfs fs/pseudofs/pseudofs.c optional pseudofs fs/pseudofs/pseudofs_fileno.c optional pseudofs fs/pseudofs/pseudofs_vncache.c optional pseudofs fs/pseudofs/pseudofs_vnops.c optional pseudofs fs/smbfs/smbfs_io.c optional smbfs fs/smbfs/smbfs_node.c optional smbfs fs/smbfs/smbfs_smb.c optional smbfs fs/smbfs/smbfs_subr.c optional smbfs fs/smbfs/smbfs_vfsops.c optional smbfs fs/smbfs/smbfs_vnops.c optional smbfs fs/udf/osta.c optional udf fs/udf/udf_iconv.c optional udf_iconv fs/udf/udf_vfsops.c optional udf fs/udf/udf_vnops.c optional udf fs/unionfs/union_subr.c optional unionfs fs/unionfs/union_vfsops.c optional unionfs fs/unionfs/union_vnops.c optional unionfs fs/tmpfs/tmpfs_vnops.c optional tmpfs fs/tmpfs/tmpfs_fifoops.c optional tmpfs fs/tmpfs/tmpfs_vfsops.c optional tmpfs fs/tmpfs/tmpfs_subr.c optional tmpfs gdb/gdb_cons.c optional gdb gdb/gdb_main.c optional gdb gdb/gdb_packet.c optional gdb geom/bde/g_bde.c optional geom_bde geom/bde/g_bde_crypt.c optional geom_bde geom/bde/g_bde_lock.c optional geom_bde geom/bde/g_bde_work.c optional geom_bde geom/cache/g_cache.c optional geom_cache geom/concat/g_concat.c optional geom_concat geom/eli/g_eli.c optional geom_eli geom/eli/g_eli_crypto.c optional geom_eli geom/eli/g_eli_ctl.c optional geom_eli geom/eli/g_eli_hmac.c optional geom_eli geom/eli/g_eli_integrity.c optional geom_eli geom/eli/g_eli_key.c optional geom_eli geom/eli/g_eli_key_cache.c optional geom_eli geom/eli/g_eli_privacy.c optional geom_eli geom/eli/pkcs5v2.c optional geom_eli geom/gate/g_gate.c optional geom_gate geom/geom_aes.c optional geom_aes geom/geom_bsd.c optional geom_bsd geom/geom_bsd_enc.c optional geom_bsd | geom_part_bsd geom/geom_ccd.c optional ccd | geom_ccd geom/geom_ctl.c standard geom/geom_dev.c standard geom/geom_disk.c standard geom/geom_dump.c standard geom/geom_event.c standard geom/geom_fox.c optional geom_fox geom/geom_flashmap.c optional fdt cfi | fdt nand | fdt mx25l | mmcsd geom/geom_io.c standard geom/geom_kern.c standard geom/geom_map.c optional geom_map geom/geom_mbr.c optional geom_mbr geom/geom_mbr_enc.c optional geom_mbr geom/geom_redboot.c optional geom_redboot geom/geom_slice.c standard geom/geom_subr.c standard geom/geom_sunlabel.c optional geom_sunlabel geom/geom_sunlabel_enc.c optional geom_sunlabel geom/geom_vfs.c standard geom/geom_vol_ffs.c optional geom_vol geom/journal/g_journal.c optional geom_journal geom/journal/g_journal_ufs.c optional geom_journal geom/label/g_label.c optional geom_label | geom_label_gpt geom/label/g_label_ext2fs.c optional geom_label geom/label/g_label_iso9660.c optional geom_label geom/label/g_label_msdosfs.c optional geom_label geom/label/g_label_ntfs.c optional geom_label geom/label/g_label_reiserfs.c optional geom_label geom/label/g_label_ufs.c optional geom_label geom/label/g_label_gpt.c optional geom_label | geom_label_gpt geom/label/g_label_disk_ident.c optional geom_label geom/linux_lvm/g_linux_lvm.c optional geom_linux_lvm geom/mirror/g_mirror.c optional geom_mirror geom/mirror/g_mirror_ctl.c optional geom_mirror geom/mountver/g_mountver.c optional geom_mountver geom/multipath/g_multipath.c optional geom_multipath geom/nop/g_nop.c optional geom_nop geom/part/g_part.c standard geom/part/g_part_if.m standard geom/part/g_part_apm.c optional geom_part_apm geom/part/g_part_bsd.c optional geom_part_bsd geom/part/g_part_bsd64.c optional geom_part_bsd64 geom/part/g_part_ebr.c optional geom_part_ebr geom/part/g_part_gpt.c optional geom_part_gpt geom/part/g_part_ldm.c optional geom_part_ldm geom/part/g_part_mbr.c optional geom_part_mbr geom/part/g_part_vtoc8.c optional geom_part_vtoc8 geom/raid/g_raid.c optional geom_raid geom/raid/g_raid_ctl.c optional geom_raid geom/raid/g_raid_md_if.m optional geom_raid geom/raid/g_raid_tr_if.m optional geom_raid geom/raid/md_ddf.c optional geom_raid geom/raid/md_intel.c optional geom_raid geom/raid/md_jmicron.c optional geom_raid geom/raid/md_nvidia.c optional geom_raid geom/raid/md_promise.c optional geom_raid geom/raid/md_sii.c optional geom_raid geom/raid/tr_concat.c optional geom_raid geom/raid/tr_raid0.c optional geom_raid geom/raid/tr_raid1.c optional geom_raid geom/raid/tr_raid1e.c optional geom_raid geom/raid/tr_raid5.c optional geom_raid geom/raid3/g_raid3.c optional geom_raid3 geom/raid3/g_raid3_ctl.c optional geom_raid3 geom/shsec/g_shsec.c optional geom_shsec geom/stripe/g_stripe.c optional geom_stripe contrib/xz-embedded/freebsd/xz_malloc.c \ optional xz_embedded | geom_uzip \ compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/" contrib/xz-embedded/linux/lib/xz/xz_crc32.c \ optional xz_embedded | geom_uzip \ compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/" contrib/xz-embedded/linux/lib/xz/xz_dec_bcj.c \ optional xz_embedded | geom_uzip \ compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/" contrib/xz-embedded/linux/lib/xz/xz_dec_lzma2.c \ optional xz_embedded | geom_uzip \ compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/" contrib/xz-embedded/linux/lib/xz/xz_dec_stream.c \ optional xz_embedded | geom_uzip \ compile-with "${NORMAL_C} -I$S/contrib/xz-embedded/freebsd/ -I$S/contrib/xz-embedded/linux/lib/xz/ -I$S/contrib/xz-embedded/linux/include/linux/" geom/uzip/g_uzip.c optional geom_uzip geom/uzip/g_uzip_lzma.c optional geom_uzip geom/uzip/g_uzip_wrkthr.c optional geom_uzip geom/uzip/g_uzip_zlib.c optional geom_uzip geom/vinum/geom_vinum.c optional geom_vinum geom/vinum/geom_vinum_create.c optional geom_vinum geom/vinum/geom_vinum_drive.c optional geom_vinum geom/vinum/geom_vinum_plex.c optional geom_vinum geom/vinum/geom_vinum_volume.c optional geom_vinum geom/vinum/geom_vinum_subr.c optional geom_vinum geom/vinum/geom_vinum_raid5.c optional geom_vinum geom/vinum/geom_vinum_share.c optional geom_vinum geom/vinum/geom_vinum_list.c optional geom_vinum geom/vinum/geom_vinum_rm.c optional geom_vinum geom/vinum/geom_vinum_init.c optional geom_vinum geom/vinum/geom_vinum_state.c optional geom_vinum geom/vinum/geom_vinum_rename.c optional geom_vinum geom/vinum/geom_vinum_move.c optional geom_vinum geom/vinum/geom_vinum_events.c optional geom_vinum geom/virstor/binstream.c optional geom_virstor geom/virstor/g_virstor.c optional geom_virstor geom/virstor/g_virstor_md.c optional geom_virstor geom/zero/g_zero.c optional geom_zero fs/ext2fs/ext2_acl.c optional ext2fs fs/ext2fs/ext2_alloc.c optional ext2fs fs/ext2fs/ext2_balloc.c optional ext2fs fs/ext2fs/ext2_bmap.c optional ext2fs fs/ext2fs/ext2_csum.c optional ext2fs fs/ext2fs/ext2_extattr.c optional ext2fs fs/ext2fs/ext2_extents.c optional ext2fs fs/ext2fs/ext2_inode.c optional ext2fs fs/ext2fs/ext2_inode_cnv.c optional ext2fs fs/ext2fs/ext2_hash.c optional ext2fs fs/ext2fs/ext2_htree.c optional ext2fs fs/ext2fs/ext2_lookup.c optional ext2fs fs/ext2fs/ext2_subr.c optional ext2fs fs/ext2fs/ext2_vfsops.c optional ext2fs fs/ext2fs/ext2_vnops.c optional ext2fs # isa/isa_if.m standard isa/isa_common.c optional isa isa/isahint.c optional isa isa/pnp.c optional isa isapnp isa/pnpparse.c optional isa isapnp fs/cd9660/cd9660_bmap.c optional cd9660 fs/cd9660/cd9660_lookup.c optional cd9660 fs/cd9660/cd9660_node.c optional cd9660 fs/cd9660/cd9660_rrip.c optional cd9660 fs/cd9660/cd9660_util.c optional cd9660 fs/cd9660/cd9660_vfsops.c optional cd9660 fs/cd9660/cd9660_vnops.c optional cd9660 fs/cd9660/cd9660_iconv.c optional cd9660_iconv kern/bus_if.m standard kern/clock_if.m standard kern/cpufreq_if.m standard kern/device_if.m standard kern/imgact_binmisc.c optional imagact_binmisc kern/imgact_elf.c standard kern/imgact_elf32.c optional compat_freebsd32 kern/imgact_shell.c standard kern/inflate.c optional gzip kern/init_main.c standard kern/init_sysent.c standard kern/ksched.c optional _kposix_priority_scheduling kern/kern_acct.c standard kern/kern_alq.c optional alq kern/kern_clock.c standard kern/kern_condvar.c standard kern/kern_conf.c standard kern/kern_cons.c standard kern/kern_cpu.c standard kern/kern_cpuset.c standard kern/kern_context.c standard kern/kern_descrip.c standard kern/kern_dtrace.c optional kdtrace_hooks kern/kern_dump.c standard kern/kern_environment.c standard kern/kern_et.c standard kern/kern_event.c standard kern/kern_exec.c standard kern/kern_exit.c standard kern/kern_fail.c standard kern/kern_ffclock.c standard kern/kern_fork.c standard kern/kern_gzio.c optional gzio kern/kern_hhook.c standard kern/kern_idle.c standard kern/kern_intr.c standard kern/kern_jail.c standard kern/kern_khelp.c standard kern/kern_kthread.c standard kern/kern_ktr.c optional ktr kern/kern_ktrace.c standard kern/kern_linker.c standard kern/kern_lock.c standard kern/kern_lockf.c standard kern/kern_lockstat.c optional kdtrace_hooks kern/kern_loginclass.c standard kern/kern_malloc.c standard kern/kern_mbuf.c standard kern/kern_mib.c standard kern/kern_module.c standard kern/kern_mtxpool.c standard kern/kern_mutex.c standard kern/kern_ntptime.c standard kern/kern_numa.c standard kern/kern_osd.c standard kern/kern_physio.c standard kern/kern_pmc.c standard kern/kern_poll.c optional device_polling kern/kern_priv.c standard kern/kern_proc.c standard kern/kern_procctl.c standard kern/kern_prot.c standard kern/kern_racct.c standard kern/kern_rangelock.c standard kern/kern_rctl.c standard kern/kern_resource.c standard kern/kern_rmlock.c standard kern/kern_rwlock.c standard kern/kern_sdt.c optional kdtrace_hooks kern/kern_sema.c standard kern/kern_sendfile.c standard kern/kern_sharedpage.c standard kern/kern_shutdown.c standard kern/kern_sig.c standard kern/kern_switch.c standard kern/kern_sx.c standard kern/kern_synch.c standard kern/kern_syscalls.c standard kern/kern_sysctl.c standard kern/kern_tc.c standard kern/kern_thr.c standard kern/kern_thread.c standard kern/kern_time.c standard kern/kern_timeout.c standard kern/kern_umtx.c standard kern/kern_uuid.c standard kern/kern_xxx.c standard kern/link_elf.c standard kern/linker_if.m standard kern/md4c.c optional netsmb kern/md5c.c standard kern/p1003_1b.c standard kern/posix4_mib.c standard kern/sched_4bsd.c optional sched_4bsd kern/sched_ule.c optional sched_ule kern/serdev_if.m standard kern/stack_protector.c standard \ compile-with "${NORMAL_C:N-fstack-protector*}" kern/subr_acl_nfs4.c optional ufs_acl | zfs kern/subr_acl_posix1e.c optional ufs_acl kern/subr_autoconf.c standard kern/subr_blist.c standard kern/subr_bus.c standard kern/subr_bus_dma.c standard kern/subr_bufring.c standard kern/subr_capability.c standard kern/subr_clock.c standard kern/subr_counter.c standard kern/subr_devstat.c standard kern/subr_disk.c standard kern/subr_eventhandler.c standard kern/subr_fattime.c standard kern/subr_firmware.c optional firmware kern/subr_gtaskqueue.c standard kern/subr_hash.c standard kern/subr_hints.c standard kern/subr_kdb.c standard kern/subr_kobj.c standard kern/subr_lock.c standard kern/subr_log.c standard kern/subr_mbpool.c optional libmbpool kern/subr_mchain.c optional libmchain kern/subr_module.c standard kern/subr_msgbuf.c standard kern/subr_param.c standard kern/subr_pcpu.c standard kern/subr_pctrie.c standard kern/subr_power.c standard kern/subr_prf.c standard kern/subr_prof.c standard kern/subr_rman.c standard kern/subr_rtc.c standard kern/subr_sbuf.c standard kern/subr_scanf.c standard kern/subr_sglist.c standard kern/subr_sleepqueue.c standard kern/subr_smp.c standard kern/subr_stack.c optional ddb | stack | ktr kern/subr_taskqueue.c standard kern/subr_terminal.c optional vt kern/subr_trap.c standard kern/subr_turnstile.c standard kern/subr_uio.c standard kern/subr_unit.c standard kern/subr_vmem.c standard kern/subr_witness.c optional witness kern/sys_capability.c standard kern/sys_generic.c standard kern/sys_pipe.c standard kern/sys_procdesc.c standard kern/sys_process.c standard kern/sys_socket.c standard kern/syscalls.c standard kern/sysv_ipc.c standard kern/sysv_msg.c optional sysvmsg kern/sysv_sem.c optional sysvsem kern/sysv_shm.c optional sysvshm kern/tty.c standard kern/tty_compat.c optional compat_43tty kern/tty_info.c standard kern/tty_inq.c standard kern/tty_outq.c standard kern/tty_pts.c standard kern/tty_tty.c standard kern/tty_ttydisc.c standard kern/uipc_accf.c standard kern/uipc_debug.c optional ddb kern/uipc_domain.c standard kern/uipc_mbuf.c standard kern/uipc_mbuf2.c standard kern/uipc_mbufhash.c standard kern/uipc_mqueue.c optional p1003_1b_mqueue kern/uipc_sem.c optional p1003_1b_semaphores kern/uipc_shm.c standard kern/uipc_sockbuf.c standard kern/uipc_socket.c standard kern/uipc_syscalls.c standard kern/uipc_usrreq.c standard kern/vfs_acl.c standard kern/vfs_aio.c standard kern/vfs_bio.c standard kern/vfs_cache.c standard kern/vfs_cluster.c standard kern/vfs_default.c standard kern/vfs_export.c standard kern/vfs_extattr.c standard kern/vfs_hash.c standard kern/vfs_init.c standard kern/vfs_lookup.c standard kern/vfs_mount.c standard kern/vfs_mountroot.c standard kern/vfs_subr.c standard kern/vfs_syscalls.c standard kern/vfs_vnops.c standard # # Kernel GSS-API # gssd.h optional kgssapi \ dependency "$S/kgssapi/gssd.x" \ compile-with "RPCGEN_CPP='${CPP}' rpcgen -hM $S/kgssapi/gssd.x | grep -v pthread.h > gssd.h" \ no-obj no-implicit-rule before-depend local \ clean "gssd.h" gssd_xdr.c optional kgssapi \ dependency "$S/kgssapi/gssd.x gssd.h" \ compile-with "RPCGEN_CPP='${CPP}' rpcgen -c $S/kgssapi/gssd.x -o gssd_xdr.c" \ no-implicit-rule before-depend local \ clean "gssd_xdr.c" gssd_clnt.c optional kgssapi \ dependency "$S/kgssapi/gssd.x gssd.h" \ compile-with "RPCGEN_CPP='${CPP}' rpcgen -lM $S/kgssapi/gssd.x | grep -v string.h > gssd_clnt.c" \ no-implicit-rule before-depend local \ clean "gssd_clnt.c" kgssapi/gss_accept_sec_context.c optional kgssapi kgssapi/gss_add_oid_set_member.c optional kgssapi kgssapi/gss_acquire_cred.c optional kgssapi kgssapi/gss_canonicalize_name.c optional kgssapi kgssapi/gss_create_empty_oid_set.c optional kgssapi kgssapi/gss_delete_sec_context.c optional kgssapi kgssapi/gss_display_status.c optional kgssapi kgssapi/gss_export_name.c optional kgssapi kgssapi/gss_get_mic.c optional kgssapi kgssapi/gss_init_sec_context.c optional kgssapi kgssapi/gss_impl.c optional kgssapi kgssapi/gss_import_name.c optional kgssapi kgssapi/gss_names.c optional kgssapi kgssapi/gss_pname_to_uid.c optional kgssapi kgssapi/gss_release_buffer.c optional kgssapi kgssapi/gss_release_cred.c optional kgssapi kgssapi/gss_release_name.c optional kgssapi kgssapi/gss_release_oid_set.c optional kgssapi kgssapi/gss_set_cred_option.c optional kgssapi kgssapi/gss_test_oid_set_member.c optional kgssapi kgssapi/gss_unwrap.c optional kgssapi kgssapi/gss_verify_mic.c optional kgssapi kgssapi/gss_wrap.c optional kgssapi kgssapi/gss_wrap_size_limit.c optional kgssapi kgssapi/gssd_prot.c optional kgssapi kgssapi/krb5/krb5_mech.c optional kgssapi kgssapi/krb5/kcrypto.c optional kgssapi kgssapi/krb5/kcrypto_aes.c optional kgssapi kgssapi/krb5/kcrypto_arcfour.c optional kgssapi kgssapi/krb5/kcrypto_des.c optional kgssapi kgssapi/krb5/kcrypto_des3.c optional kgssapi kgssapi/kgss_if.m optional kgssapi kgssapi/gsstest.c optional kgssapi_debug # These files in libkern/ are those needed by all architectures. Some # of the files in libkern/ are only needed on some architectures, e.g., # libkern/divdi3.c is needed by i386 but not alpha. Also, some of these # routines may be optimized for a particular platform. In either case, # the file should be moved to conf/files. from here. # libkern/arc4random.c standard crypto/chacha20/chacha.c standard libkern/asprintf.c standard libkern/bcd.c standard libkern/bsearch.c standard libkern/crc32.c standard libkern/explicit_bzero.c standard libkern/fnmatch.c standard libkern/iconv.c optional libiconv libkern/iconv_converter_if.m optional libiconv libkern/iconv_ucs.c optional libiconv libkern/iconv_xlat.c optional libiconv libkern/iconv_xlat16.c optional libiconv libkern/inet_aton.c standard libkern/inet_ntoa.c standard libkern/inet_ntop.c standard libkern/inet_pton.c standard libkern/jenkins_hash.c standard libkern/murmur3_32.c standard libkern/mcount.c optional profiling-routine libkern/memcchr.c standard libkern/memchr.c standard libkern/memcmp.c standard libkern/memmem.c optional gdb libkern/qsort.c standard libkern/qsort_r.c standard libkern/random.c standard libkern/scanc.c standard libkern/strcasecmp.c standard libkern/strcat.c standard libkern/strchr.c standard libkern/strcmp.c standard libkern/strcpy.c standard libkern/strcspn.c standard libkern/strdup.c standard libkern/strndup.c standard libkern/strlcat.c standard libkern/strlcpy.c standard libkern/strlen.c standard libkern/strncat.c standard libkern/strncmp.c standard libkern/strncpy.c standard libkern/strnlen.c standard libkern/strrchr.c standard libkern/strsep.c standard libkern/strspn.c standard libkern/strstr.c standard libkern/strtol.c standard libkern/strtoq.c standard libkern/strtoul.c standard libkern/strtouq.c standard libkern/strvalid.c standard libkern/timingsafe_bcmp.c standard libkern/zlib.c optional crypto | geom_uzip | ipsec | \ ipsec_support | mxge | netgraph_deflate | ddb_ctf | gzio net/altq/altq_cbq.c optional altq net/altq/altq_cdnr.c optional altq net/altq/altq_codel.c optional altq net/altq/altq_hfsc.c optional altq net/altq/altq_fairq.c optional altq net/altq/altq_priq.c optional altq net/altq/altq_red.c optional altq net/altq/altq_rio.c optional altq net/altq/altq_rmclass.c optional altq net/altq/altq_subr.c optional altq net/bpf.c standard net/bpf_buffer.c optional bpf net/bpf_jitter.c optional bpf_jitter net/bpf_filter.c optional bpf | netgraph_bpf net/bpf_zerocopy.c optional bpf net/bridgestp.c optional bridge | if_bridge net/flowtable.c optional flowtable inet | flowtable inet6 net/ieee8023ad_lacp.c optional lagg net/if.c standard net/if_arcsubr.c optional arcnet net/if_bridge.c optional bridge inet | if_bridge inet net/if_clone.c standard net/if_dead.c standard net/if_debug.c optional ddb net/if_disc.c optional disc net/if_edsc.c optional edsc net/if_enc.c optional enc inet | enc inet6 net/if_epair.c optional epair net/if_ethersubr.c optional ether net/if_fddisubr.c optional fddi net/if_fwsubr.c optional fwip net/if_gif.c optional gif inet | gif inet6 | \ netgraph_gif inet | netgraph_gif inet6 net/if_gre.c optional gre inet | gre inet6 net/if_ipsec.c optional inet ipsec | inet6 ipsec net/if_iso88025subr.c optional token net/if_lagg.c optional lagg net/if_loop.c optional loop net/if_llatbl.c standard net/if_me.c optional me inet net/if_media.c standard net/if_mib.c standard net/if_spppfr.c optional sppp | netgraph_sppp net/if_spppsubr.c optional sppp | netgraph_sppp net/if_stf.c optional stf inet inet6 net/if_tun.c optional tun net/if_tap.c optional tap net/if_vlan.c optional vlan net/if_vxlan.c optional vxlan inet | vxlan inet6 net/ifdi_if.m optional ether pci net/iflib.c optional ether pci net/mp_ring.c optional ether net/mppcc.c optional netgraph_mppc_compression net/mppcd.c optional netgraph_mppc_compression net/netisr.c standard net/pfil.c optional ether | inet net/radix.c standard net/radix_mpath.c standard net/raw_cb.c standard net/raw_usrreq.c standard net/route.c standard net/rss_config.c optional inet rss | inet6 rss net/rtsock.c standard net/slcompress.c optional netgraph_vjc | sppp | \ netgraph_sppp net/toeplitz.c optional inet rss | inet6 rss net/vnet.c optional vimage net80211/ieee80211.c optional wlan net80211/ieee80211_acl.c optional wlan wlan_acl net80211/ieee80211_action.c optional wlan net80211/ieee80211_ageq.c optional wlan net80211/ieee80211_adhoc.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_ageq.c optional wlan net80211/ieee80211_amrr.c optional wlan | wlan_amrr net80211/ieee80211_crypto.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_crypto_ccmp.c optional wlan wlan_ccmp net80211/ieee80211_crypto_none.c optional wlan net80211/ieee80211_crypto_tkip.c optional wlan wlan_tkip net80211/ieee80211_crypto_wep.c optional wlan wlan_wep net80211/ieee80211_ddb.c optional wlan ddb net80211/ieee80211_dfs.c optional wlan net80211/ieee80211_freebsd.c optional wlan net80211/ieee80211_hostap.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_ht.c optional wlan net80211/ieee80211_hwmp.c optional wlan ieee80211_support_mesh net80211/ieee80211_input.c optional wlan net80211/ieee80211_ioctl.c optional wlan net80211/ieee80211_mesh.c optional wlan ieee80211_support_mesh \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_monitor.c optional wlan net80211/ieee80211_node.c optional wlan net80211/ieee80211_output.c optional wlan net80211/ieee80211_phy.c optional wlan net80211/ieee80211_power.c optional wlan net80211/ieee80211_proto.c optional wlan net80211/ieee80211_radiotap.c optional wlan net80211/ieee80211_ratectl.c optional wlan net80211/ieee80211_ratectl_none.c optional wlan net80211/ieee80211_regdomain.c optional wlan net80211/ieee80211_rssadapt.c optional wlan wlan_rssadapt net80211/ieee80211_scan.c optional wlan net80211/ieee80211_scan_sta.c optional wlan net80211/ieee80211_sta.c optional wlan \ compile-with "${NORMAL_C} -Wno-unused-function" net80211/ieee80211_superg.c optional wlan ieee80211_support_superg net80211/ieee80211_scan_sw.c optional wlan net80211/ieee80211_tdma.c optional wlan ieee80211_support_tdma net80211/ieee80211_vht.c optional wlan net80211/ieee80211_wds.c optional wlan net80211/ieee80211_xauth.c optional wlan wlan_xauth net80211/ieee80211_alq.c optional wlan ieee80211_alq netgraph/atm/ccatm/ng_ccatm.c optional ngatm_ccatm \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/ngatmbase.c optional ngatm_atmbase \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscfu/ng_sscfu.c optional ngatm_sscfu \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/sscop/ng_sscop.c optional ngatm_sscop \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/atm/uni/ng_uni.c optional ngatm_uni \ compile-with "${NORMAL_C} -I$S/contrib/ngatm" netgraph/bluetooth/common/ng_bluetooth.c optional netgraph_bluetooth netgraph/bluetooth/drivers/bt3c/ng_bt3c_pccard.c optional netgraph_bluetooth_bt3c netgraph/bluetooth/drivers/h4/ng_h4.c optional netgraph_bluetooth_h4 netgraph/bluetooth/drivers/ubt/ng_ubt.c optional netgraph_bluetooth_ubt usb netgraph/bluetooth/drivers/ubtbcmfw/ubtbcmfw.c optional netgraph_bluetooth_ubtbcmfw usb netgraph/bluetooth/hci/ng_hci_cmds.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_evnt.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_main.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_misc.c optional netgraph_bluetooth_hci netgraph/bluetooth/hci/ng_hci_ulpi.c optional netgraph_bluetooth_hci netgraph/bluetooth/l2cap/ng_l2cap_cmds.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_evnt.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_llpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_main.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_misc.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/l2cap/ng_l2cap_ulpi.c optional netgraph_bluetooth_l2cap netgraph/bluetooth/socket/ng_btsocket.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_hci_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_l2cap_raw.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_rfcomm.c optional netgraph_bluetooth_socket netgraph/bluetooth/socket/ng_btsocket_sco.c optional netgraph_bluetooth_socket netgraph/netflow/netflow.c optional netgraph_netflow netgraph/netflow/netflow_v9.c optional netgraph_netflow netgraph/netflow/ng_netflow.c optional netgraph_netflow netgraph/ng_UI.c optional netgraph_UI netgraph/ng_async.c optional netgraph_async netgraph/ng_atmllc.c optional netgraph_atmllc netgraph/ng_base.c optional netgraph netgraph/ng_bpf.c optional netgraph_bpf netgraph/ng_bridge.c optional netgraph_bridge netgraph/ng_car.c optional netgraph_car netgraph/ng_cisco.c optional netgraph_cisco netgraph/ng_deflate.c optional netgraph_deflate netgraph/ng_device.c optional netgraph_device netgraph/ng_echo.c optional netgraph_echo netgraph/ng_eiface.c optional netgraph_eiface netgraph/ng_ether.c optional netgraph_ether netgraph/ng_ether_echo.c optional netgraph_ether_echo netgraph/ng_frame_relay.c optional netgraph_frame_relay netgraph/ng_gif.c optional netgraph_gif inet6 | netgraph_gif inet netgraph/ng_gif_demux.c optional netgraph_gif_demux netgraph/ng_hole.c optional netgraph_hole netgraph/ng_iface.c optional netgraph_iface netgraph/ng_ip_input.c optional netgraph_ip_input netgraph/ng_ipfw.c optional netgraph_ipfw inet ipfirewall netgraph/ng_ksocket.c optional netgraph_ksocket netgraph/ng_l2tp.c optional netgraph_l2tp netgraph/ng_lmi.c optional netgraph_lmi netgraph/ng_mppc.c optional netgraph_mppc_compression | \ netgraph_mppc_encryption netgraph/ng_nat.c optional netgraph_nat inet libalias netgraph/ng_one2many.c optional netgraph_one2many netgraph/ng_parse.c optional netgraph netgraph/ng_patch.c optional netgraph_patch netgraph/ng_pipe.c optional netgraph_pipe netgraph/ng_ppp.c optional netgraph_ppp netgraph/ng_pppoe.c optional netgraph_pppoe netgraph/ng_pptpgre.c optional netgraph_pptpgre netgraph/ng_pred1.c optional netgraph_pred1 netgraph/ng_rfc1490.c optional netgraph_rfc1490 netgraph/ng_socket.c optional netgraph_socket netgraph/ng_split.c optional netgraph_split netgraph/ng_sppp.c optional netgraph_sppp netgraph/ng_tag.c optional netgraph_tag netgraph/ng_tcpmss.c optional netgraph_tcpmss netgraph/ng_tee.c optional netgraph_tee netgraph/ng_tty.c optional netgraph_tty netgraph/ng_vjc.c optional netgraph_vjc netgraph/ng_vlan.c optional netgraph_vlan netinet/accf_data.c optional accept_filter_data inet netinet/accf_dns.c optional accept_filter_dns inet netinet/accf_http.c optional accept_filter_http inet netinet/if_ether.c optional inet ether netinet/igmp.c optional inet netinet/in.c optional inet netinet/in_debug.c optional inet ddb netinet/in_kdtrace.c optional inet | inet6 netinet/ip_carp.c optional inet carp | inet6 carp netinet/in_fib.c optional inet netinet/in_gif.c optional gif inet | netgraph_gif inet netinet/ip_gre.c optional gre inet netinet/ip_id.c optional inet netinet/in_jail.c optional inet netinet/in_mcast.c optional inet netinet/in_pcb.c optional inet | inet6 netinet/in_pcbgroup.c optional inet pcbgroup | inet6 pcbgroup netinet/in_prot.c optional inet | inet6 netinet/in_proto.c optional inet | inet6 netinet/in_rmx.c optional inet netinet/in_rss.c optional inet rss netinet/ip_divert.c optional inet ipdivert ipfirewall netinet/ip_ecn.c optional inet | inet6 netinet/ip_encap.c optional inet | inet6 netinet/ip_fastfwd.c optional inet netinet/ip_icmp.c optional inet | inet6 netinet/ip_input.c optional inet netinet/ip_mroute.c optional mrouting inet netinet/ip_options.c optional inet netinet/ip_output.c optional inet netinet/ip_reass.c optional inet netinet/raw_ip.c optional inet | inet6 netinet/cc/cc.c optional inet | inet6 netinet/cc/cc_newreno.c optional inet | inet6 netinet/sctp_asconf.c optional inet sctp | inet6 sctp netinet/sctp_auth.c optional inet sctp | inet6 sctp netinet/sctp_bsd_addr.c optional inet sctp | inet6 sctp netinet/sctp_cc_functions.c optional inet sctp | inet6 sctp netinet/sctp_crc32.c optional inet sctp | inet6 sctp netinet/sctp_indata.c optional inet sctp | inet6 sctp netinet/sctp_input.c optional inet sctp | inet6 sctp netinet/sctp_output.c optional inet sctp | inet6 sctp netinet/sctp_pcb.c optional inet sctp | inet6 sctp netinet/sctp_peeloff.c optional inet sctp | inet6 sctp netinet/sctp_ss_functions.c optional inet sctp | inet6 sctp netinet/sctp_syscalls.c optional inet sctp | inet6 sctp netinet/sctp_sysctl.c optional inet sctp | inet6 sctp netinet/sctp_timer.c optional inet sctp | inet6 sctp netinet/sctp_usrreq.c optional inet sctp | inet6 sctp netinet/sctputil.c optional inet sctp | inet6 sctp netinet/siftr.c optional inet siftr alq | inet6 siftr alq netinet/tcp_debug.c optional tcpdebug netinet/tcp_fastopen.c optional inet tcp_rfc7413 | inet6 tcp_rfc7413 netinet/tcp_hostcache.c optional inet | inet6 netinet/tcp_input.c optional inet | inet6 netinet/tcp_lro.c optional inet | inet6 netinet/tcp_output.c optional inet | inet6 netinet/tcp_offload.c optional tcp_offload inet | tcp_offload inet6 netinet/tcp_pcap.c optional inet tcppcap | inet6 tcppcap netinet/tcp_reass.c optional inet | inet6 netinet/tcp_sack.c optional inet | inet6 netinet/tcp_subr.c optional inet | inet6 netinet/tcp_syncache.c optional inet | inet6 netinet/tcp_timer.c optional inet | inet6 netinet/tcp_timewait.c optional inet | inet6 netinet/tcp_usrreq.c optional inet | inet6 netinet/udp_usrreq.c optional inet | inet6 netinet/libalias/alias.c optional libalias inet | netgraph_nat inet netinet/libalias/alias_db.c optional libalias inet | netgraph_nat inet netinet/libalias/alias_mod.c optional libalias | netgraph_nat netinet/libalias/alias_proxy.c optional libalias inet | netgraph_nat inet netinet/libalias/alias_util.c optional libalias inet | netgraph_nat inet netinet/libalias/alias_sctp.c optional libalias inet | netgraph_nat inet netinet6/dest6.c optional inet6 netinet6/frag6.c optional inet6 netinet6/icmp6.c optional inet6 netinet6/in6.c optional inet6 netinet6/in6_cksum.c optional inet6 netinet6/in6_fib.c optional inet6 netinet6/in6_gif.c optional gif inet6 | netgraph_gif inet6 netinet6/in6_ifattach.c optional inet6 netinet6/in6_jail.c optional inet6 netinet6/in6_mcast.c optional inet6 netinet6/in6_pcb.c optional inet6 netinet6/in6_pcbgroup.c optional inet6 pcbgroup netinet6/in6_proto.c optional inet6 netinet6/in6_rmx.c optional inet6 netinet6/in6_rss.c optional inet6 rss netinet6/in6_src.c optional inet6 netinet6/ip6_fastfwd.c optional inet6 netinet6/ip6_forward.c optional inet6 netinet6/ip6_gre.c optional gre inet6 netinet6/ip6_id.c optional inet6 netinet6/ip6_input.c optional inet6 netinet6/ip6_mroute.c optional mrouting inet6 netinet6/ip6_output.c optional inet6 netinet6/mld6.c optional inet6 netinet6/nd6.c optional inet6 netinet6/nd6_nbr.c optional inet6 netinet6/nd6_rtr.c optional inet6 netinet6/raw_ip6.c optional inet6 netinet6/route6.c optional inet6 netinet6/scope6.c optional inet6 netinet6/sctp6_usrreq.c optional inet6 sctp netinet6/udp6_usrreq.c optional inet6 netipsec/ipsec.c optional ipsec inet | ipsec inet6 netipsec/ipsec_input.c optional ipsec inet | ipsec inet6 netipsec/ipsec_mbuf.c optional ipsec inet | ipsec inet6 netipsec/ipsec_mod.c optional ipsec inet | ipsec inet6 netipsec/ipsec_output.c optional ipsec inet | ipsec inet6 netipsec/ipsec_pcb.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 netipsec/key.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 netipsec/key_debug.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 netipsec/keysock.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 netipsec/subr_ipsec.c optional ipsec inet | ipsec inet6 | \ ipsec_support inet | ipsec_support inet6 netipsec/udpencap.c optional ipsec inet netipsec/xform_ah.c optional ipsec inet | ipsec inet6 netipsec/xform_esp.c optional ipsec inet | ipsec inet6 netipsec/xform_ipcomp.c optional ipsec inet | ipsec inet6 netipsec/xform_tcp.c optional ipsec inet tcp_signature | \ ipsec inet6 tcp_signature | ipsec_support inet tcp_signature | \ ipsec_support inet6 tcp_signature netpfil/ipfw/dn_aqm_codel.c optional inet dummynet netpfil/ipfw/dn_aqm_pie.c optional inet dummynet netpfil/ipfw/dn_heap.c optional inet dummynet netpfil/ipfw/dn_sched_fifo.c optional inet dummynet netpfil/ipfw/dn_sched_fq_codel.c optional inet dummynet netpfil/ipfw/dn_sched_fq_pie.c optional inet dummynet netpfil/ipfw/dn_sched_prio.c optional inet dummynet netpfil/ipfw/dn_sched_qfq.c optional inet dummynet netpfil/ipfw/dn_sched_rr.c optional inet dummynet netpfil/ipfw/dn_sched_wf2q.c optional inet dummynet netpfil/ipfw/ip_dummynet.c optional inet dummynet netpfil/ipfw/ip_dn_io.c optional inet dummynet netpfil/ipfw/ip_dn_glue.c optional inet dummynet netpfil/ipfw/ip_fw2.c optional inet ipfirewall netpfil/ipfw/ip_fw_bpf.c optional inet ipfirewall netpfil/ipfw/ip_fw_dynamic.c optional inet ipfirewall netpfil/ipfw/ip_fw_eaction.c optional inet ipfirewall netpfil/ipfw/ip_fw_log.c optional inet ipfirewall netpfil/ipfw/ip_fw_pfil.c optional inet ipfirewall netpfil/ipfw/ip_fw_sockopt.c optional inet ipfirewall netpfil/ipfw/ip_fw_table.c optional inet ipfirewall netpfil/ipfw/ip_fw_table_algo.c optional inet ipfirewall netpfil/ipfw/ip_fw_table_value.c optional inet ipfirewall netpfil/ipfw/ip_fw_iface.c optional inet ipfirewall netpfil/ipfw/ip_fw_nat.c optional inet ipfirewall_nat netpfil/ipfw/nat64/ip_fw_nat64.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nat64/nat64lsn.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nat64/nat64lsn_control.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nat64/nat64stl.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nat64/nat64stl_control.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nat64/nat64_translate.c optional inet inet6 ipfirewall \ ipfirewall_nat64 netpfil/ipfw/nptv6/ip_fw_nptv6.c optional inet inet6 ipfirewall \ ipfirewall_nptv6 netpfil/ipfw/nptv6/nptv6.c optional inet inet6 ipfirewall \ ipfirewall_nptv6 netpfil/ipfw/pmod/ip_fw_pmod.c optional inet ipfirewall_pmod netpfil/ipfw/pmod/tcpmod.c optional inet ipfirewall_pmod netpfil/pf/if_pflog.c optional pflog pf inet netpfil/pf/if_pfsync.c optional pfsync pf inet netpfil/pf/pf.c optional pf inet netpfil/pf/pf_if.c optional pf inet netpfil/pf/pf_ioctl.c optional pf inet netpfil/pf/pf_lb.c optional pf inet netpfil/pf/pf_norm.c optional pf inet netpfil/pf/pf_osfp.c optional pf inet netpfil/pf/pf_ruleset.c optional pf inet netpfil/pf/pf_table.c optional pf inet netpfil/pf/in4_cksum.c optional pf inet netsmb/smb_conn.c optional netsmb netsmb/smb_crypt.c optional netsmb netsmb/smb_dev.c optional netsmb netsmb/smb_iod.c optional netsmb netsmb/smb_rq.c optional netsmb netsmb/smb_smb.c optional netsmb netsmb/smb_subr.c optional netsmb netsmb/smb_trantcp.c optional netsmb netsmb/smb_usr.c optional netsmb nfs/bootp_subr.c optional bootp nfscl nfs/krpc_subr.c optional bootp nfscl nfs/nfs_diskless.c optional nfscl nfs_root nfs/nfs_fha.c optional nfsd nfs/nfs_lock.c optional nfscl | nfslockd | nfsd nfs/nfs_nfssvc.c optional nfscl | nfsd nlm/nlm_advlock.c optional nfslockd | nfsd nlm/nlm_prot_clnt.c optional nfslockd | nfsd nlm/nlm_prot_impl.c optional nfslockd | nfsd nlm/nlm_prot_server.c optional nfslockd | nfsd nlm/nlm_prot_svc.c optional nfslockd | nfsd nlm/nlm_prot_xdr.c optional nfslockd | nfsd nlm/sm_inter_xdr.c optional nfslockd | nfsd # Linux Kernel Programming Interface compat/linuxkpi/common/src/linux_kmod.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_compat.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_current.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_hrtimer.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_kthread.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_lock.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_page.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_pci.c optional compat_linuxkpi pci \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_tasklet.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_idr.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_radix.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_rcu.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C} -I$S/contrib/ck/include" compat/linuxkpi/common/src/linux_schedule.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_slab.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_usb.c optional compat_linuxkpi usb \ compile-with "${LINUXKPI_C}" compat/linuxkpi/common/src/linux_work.c optional compat_linuxkpi \ compile-with "${LINUXKPI_C}" # OpenFabrics Enterprise Distribution (Infiniband) ofed/drivers/infiniband/core/addr.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/agent.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/cache.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" # XXX Mad.c must be ordered before cm.c for sysinit sets to occur in # the correct order. ofed/drivers/infiniband/core/mad.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/cm.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/ -Wno-unused-function" ofed/drivers/infiniband/core/cma.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/device.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/fmr_pool.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/iwcm.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/mad_rmpp.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/multicast.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/packer.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/peer_mem.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/sa_query.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/smi.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/sysfs.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ucm.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ucma.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/ud_header.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/umem.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/user_mad.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_cmd.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_main.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/uverbs_marshall.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/core/verbs.c optional ofed \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/core/" ofed/drivers/infiniband/ulp/ipoib/ipoib_cm.c optional ipoib \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" #ofed/drivers/infiniband/ulp/ipoib/ipoib_fs.c optional ipoib \ # compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_ib.c optional ipoib \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_main.c optional ipoib \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_multicast.c optional ipoib \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/ipoib/ipoib_verbs.c optional ipoib \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" #ofed/drivers/infiniband/ulp/ipoib/ipoib_vlan.c optional ipoib \ # compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/ipoib/" ofed/drivers/infiniband/ulp/sdp/sdp_bcopy.c optional sdp inet \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_main.c optional sdp inet \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_rx.c optional sdp inet \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_cma.c optional sdp inet \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" ofed/drivers/infiniband/ulp/sdp/sdp_tx.c optional sdp inet \ compile-with "${OFED_C} -I$S/ofed/drivers/infiniband/ulp/sdp/" dev/mlx4/mlx4_ib/mlx4_ib_alias_GUID.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_mcg.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_sysfs.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_cm.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_ah.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_cq.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_doorbell.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_mad.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_main.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_exp.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_mr.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_qp.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_srq.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_ib/mlx4_ib_wc.c optional mlx4ib pci ofed \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_alloc.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_catas.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_cmd.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_cq.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_eq.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_fw.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_icm.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_intf.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_main.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_mcg.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_mr.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_pd.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_port.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_profile.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_qp.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_reset.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_sense.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_srq.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_resource_tracker.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_core/mlx4_sys_tune.c optional mlx4 pci \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_cq.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_main.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_netdev.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_port.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_resources.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_rx.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx4/mlx4_en/mlx4_en_tx.c optional mlx4en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_alloc.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_cmd.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_cq.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_diagnostics.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_eq.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_flow_table.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_fw.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_health.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mad.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_main.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mcg.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_mr.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_pagealloc.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_pd.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_port.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_qp.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_srq.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_transobj.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_uar.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_vport.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_core/mlx5_wq.c optional mlx5 pci \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_ethtool.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_main.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_tx.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_flow_table.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_rx.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" dev/mlx5/mlx5_en/mlx5_en_txrx.c optional mlx5en pci inet inet6 \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_allocator.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_av.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_catas.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_cmd.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_cq.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_eq.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mad.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_main.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mcg.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_memfree.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_mr.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_pd.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_profile.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_provider.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_qp.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_reset.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_srq.c optional mthca \ compile-with "${OFED_C}" ofed/drivers/infiniband/hw/mthca/mthca_uar.c optional mthca \ compile-with "${OFED_C}" # crypto support opencrypto/cast.c optional crypto | ipsec | ipsec_support opencrypto/criov.c optional crypto | ipsec | ipsec_support opencrypto/crypto.c optional crypto | ipsec | ipsec_support opencrypto/cryptodev.c optional cryptodev opencrypto/cryptodev_if.m optional crypto | ipsec | ipsec_support opencrypto/cryptosoft.c optional crypto | ipsec | ipsec_support opencrypto/cryptodeflate.c optional crypto | ipsec | ipsec_support opencrypto/gmac.c optional crypto | ipsec | ipsec_support opencrypto/gfmult.c optional crypto | ipsec | ipsec_support opencrypto/rmd160.c optional crypto | ipsec | ipsec_support opencrypto/skipjack.c optional crypto | ipsec | ipsec_support opencrypto/xform.c optional crypto | ipsec | ipsec_support rpc/auth_none.c optional krpc | nfslockd | nfscl | nfsd rpc/auth_unix.c optional krpc | nfslockd | nfscl | nfsd rpc/authunix_prot.c optional krpc | nfslockd | nfscl | nfsd rpc/clnt_bck.c optional krpc | nfslockd | nfscl | nfsd rpc/clnt_dg.c optional krpc | nfslockd | nfscl | nfsd rpc/clnt_rc.c optional krpc | nfslockd | nfscl | nfsd rpc/clnt_vc.c optional krpc | nfslockd | nfscl | nfsd rpc/getnetconfig.c optional krpc | nfslockd | nfscl | nfsd rpc/replay.c optional krpc | nfslockd | nfscl | nfsd rpc/rpc_callmsg.c optional krpc | nfslockd | nfscl | nfsd rpc/rpc_generic.c optional krpc | nfslockd | nfscl | nfsd rpc/rpc_prot.c optional krpc | nfslockd | nfscl | nfsd rpc/rpcb_clnt.c optional krpc | nfslockd | nfscl | nfsd rpc/rpcb_prot.c optional krpc | nfslockd | nfscl | nfsd rpc/svc.c optional krpc | nfslockd | nfscl | nfsd rpc/svc_auth.c optional krpc | nfslockd | nfscl | nfsd rpc/svc_auth_unix.c optional krpc | nfslockd | nfscl | nfsd rpc/svc_dg.c optional krpc | nfslockd | nfscl | nfsd rpc/svc_generic.c optional krpc | nfslockd | nfscl | nfsd rpc/svc_vc.c optional krpc | nfslockd | nfscl | nfsd rpc/rpcsec_gss/rpcsec_gss.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi rpc/rpcsec_gss/rpcsec_gss_conf.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi rpc/rpcsec_gss/rpcsec_gss_misc.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi rpc/rpcsec_gss/rpcsec_gss_prot.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi rpc/rpcsec_gss/svc_rpcsec_gss.c optional krpc kgssapi | nfslockd kgssapi | nfscl kgssapi | nfsd kgssapi security/audit/audit.c optional audit security/audit/audit_arg.c optional audit security/audit/audit_bsm.c optional audit security/audit/audit_bsm_db.c optional audit security/audit/audit_bsm_klib.c optional audit security/audit/audit_dtrace.c optional dtaudit audit | dtraceall audit compile-with "${CDDL_C}" security/audit/audit_pipe.c optional audit security/audit/audit_syscalls.c standard security/audit/audit_trigger.c optional audit security/audit/audit_worker.c optional audit security/audit/bsm_domain.c optional audit security/audit/bsm_errno.c optional audit security/audit/bsm_fcntl.c optional audit security/audit/bsm_socket_type.c optional audit security/audit/bsm_token.c optional audit security/mac/mac_audit.c optional mac audit security/mac/mac_cred.c optional mac security/mac/mac_framework.c optional mac security/mac/mac_inet.c optional mac inet | mac inet6 security/mac/mac_inet6.c optional mac inet6 security/mac/mac_label.c optional mac security/mac/mac_net.c optional mac security/mac/mac_pipe.c optional mac security/mac/mac_posix_sem.c optional mac security/mac/mac_posix_shm.c optional mac security/mac/mac_priv.c optional mac security/mac/mac_process.c optional mac security/mac/mac_socket.c optional mac security/mac/mac_syscalls.c standard security/mac/mac_system.c optional mac security/mac/mac_sysv_msg.c optional mac security/mac/mac_sysv_sem.c optional mac security/mac/mac_sysv_shm.c optional mac security/mac/mac_vfs.c optional mac security/mac_biba/mac_biba.c optional mac_biba security/mac_bsdextended/mac_bsdextended.c optional mac_bsdextended security/mac_bsdextended/ugidfw_system.c optional mac_bsdextended security/mac_bsdextended/ugidfw_vnode.c optional mac_bsdextended security/mac_ifoff/mac_ifoff.c optional mac_ifoff security/mac_lomac/mac_lomac.c optional mac_lomac security/mac_mls/mac_mls.c optional mac_mls security/mac_none/mac_none.c optional mac_none security/mac_partition/mac_partition.c optional mac_partition security/mac_portacl/mac_portacl.c optional mac_portacl security/mac_seeotheruids/mac_seeotheruids.c optional mac_seeotheruids security/mac_stub/mac_stub.c optional mac_stub security/mac_test/mac_test.c optional mac_test teken/teken.c optional sc | vt ufs/ffs/ffs_alloc.c optional ffs ufs/ffs/ffs_balloc.c optional ffs ufs/ffs/ffs_inode.c optional ffs ufs/ffs/ffs_snapshot.c optional ffs ufs/ffs/ffs_softdep.c optional ffs ufs/ffs/ffs_subr.c optional ffs ufs/ffs/ffs_tables.c optional ffs ufs/ffs/ffs_vfsops.c optional ffs ufs/ffs/ffs_vnops.c optional ffs ufs/ffs/ffs_rawread.c optional ffs directio ufs/ffs/ffs_suspend.c optional ffs ufs/ufs/ufs_acl.c optional ffs ufs/ufs/ufs_bmap.c optional ffs ufs/ufs/ufs_dirhash.c optional ffs ufs/ufs/ufs_extattr.c optional ffs ufs/ufs/ufs_gjournal.c optional ffs UFS_GJOURNAL ufs/ufs/ufs_inode.c optional ffs ufs/ufs/ufs_lookup.c optional ffs ufs/ufs/ufs_quota.c optional ffs ufs/ufs/ufs_vfsops.c optional ffs ufs/ufs/ufs_vnops.c optional ffs vm/default_pager.c standard vm/device_pager.c standard vm/phys_pager.c standard vm/redzone.c optional DEBUG_REDZONE vm/sg_pager.c standard vm/swap_pager.c standard vm/uma_core.c standard vm/uma_dbg.c standard vm/memguard.c optional DEBUG_MEMGUARD vm/vm_fault.c standard vm/vm_glue.c standard vm/vm_init.c standard vm/vm_kern.c standard vm/vm_map.c standard vm/vm_meter.c standard vm/vm_mmap.c standard vm/vm_object.c standard vm/vm_page.c standard vm/vm_pageout.c standard vm/vm_pager.c standard vm/vm_phys.c standard vm/vm_radix.c standard vm/vm_reserv.c standard vm/vm_domain.c standard vm/vm_unix.c standard vm/vnode_pager.c standard xen/features.c optional xenhvm xen/xenbus/xenbus_if.m optional xenhvm xen/xenbus/xenbus.c optional xenhvm xen/xenbus/xenbusb_if.m optional xenhvm xen/xenbus/xenbusb.c optional xenhvm xen/xenbus/xenbusb_front.c optional xenhvm xen/xenbus/xenbusb_back.c optional xenhvm xen/xenmem/xenmem_if.m optional xenhvm xdr/xdr.c optional krpc | nfslockd | nfscl | nfsd xdr/xdr_array.c optional krpc | nfslockd | nfscl | nfsd xdr/xdr_mbuf.c optional krpc | nfslockd | nfscl | nfsd xdr/xdr_mem.c optional krpc | nfslockd | nfscl | nfsd xdr/xdr_reference.c optional krpc | nfslockd | nfscl | nfsd xdr/xdr_sizeof.c optional krpc | nfslockd | nfscl | nfsd Index: projects/make-check-sandbox/sys/dev/cxgbe/common/t4_hw.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/common/t4_hw.h (revision 322021) +++ projects/make-check-sandbox/sys/dev/cxgbe/common/t4_hw.h (revision 322022) @@ -1,291 +1,300 @@ /*- * Copyright (c) 2011, 2016 Chelsio Communications, Inc. * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef __T4_HW_H #define __T4_HW_H #include "osdep.h" enum { NCHAN = 4, /* # of HW channels */ T6_NCHAN = 2, MAX_NCHAN = 4, MAX_MTU = 9600, /* max MAC MTU, excluding header + FCS */ EEPROMSIZE = 17408, /* Serial EEPROM physical size */ EEPROMVSIZE = 32768, /* Serial EEPROM virtual address space size */ EEPROMPFSIZE = 1024, /* EEPROM writable area size for PFn, n>0 */ RSS_NENTRIES = 2048, /* # of entries in RSS mapping table */ TCB_SIZE = 128, /* TCB size */ NMTUS = 16, /* size of MTU table */ NCCTRL_WIN = 32, /* # of congestion control windows */ NTX_SCHED = 8, /* # of HW Tx scheduling queues */ PM_NSTATS = 5, /* # of PM stats */ T6_PM_NSTATS = 7, MAX_PM_NSTATS = 7, MBOX_LEN = 64, /* mailbox size in bytes */ NTRACE = 4, /* # of tracing filters */ TRACE_LEN = 112, /* length of trace data and mask */ FILTER_OPT_LEN = 36, /* filter tuple width of optional components */ NWOL_PAT = 8, /* # of WoL patterns */ WOL_PAT_LEN = 128, /* length of WoL patterns */ UDBS_SEG_SIZE = 128, /* Segment size of BAR2 doorbells */ UDBS_SEG_SHIFT = 7, /* log2(UDBS_SEG_SIZE) */ UDBS_DB_OFFSET = 8, /* offset of the 4B doorbell in a segment */ UDBS_WR_OFFSET = 64, /* offset of the work request in a segment */ }; enum { CIM_NUM_IBQ = 6, /* # of CIM IBQs */ CIM_NUM_OBQ = 6, /* # of CIM OBQs */ CIM_NUM_OBQ_T5 = 8, /* # of CIM OBQs for T5 adapter */ CIMLA_SIZE = 2048, /* # of 32-bit words in CIM LA */ CIM_PIFLA_SIZE = 64, /* # of 192-bit words in CIM PIF LA */ CIM_MALA_SIZE = 64, /* # of 160-bit words in CIM MA LA */ CIM_IBQ_SIZE = 128, /* # of 128-bit words in a CIM IBQ */ CIM_OBQ_SIZE = 128, /* # of 128-bit words in a CIM OBQ */ TPLA_SIZE = 128, /* # of 64-bit words in TP LA */ ULPRX_LA_SIZE = 512, /* # of 256-bit words in ULP_RX LA */ }; enum { SF_PAGE_SIZE = 256, /* serial flash page size */ SF_SEC_SIZE = 64 * 1024, /* serial flash sector size */ }; /* SGE context types */ enum ctxt_type { CTXT_EGRESS, CTXT_INGRESS, CTXT_FLM, CTXT_CNM }; enum { RSP_TYPE_FLBUF, RSP_TYPE_CPL, RSP_TYPE_INTR }; /* response entry types */ enum { MBOX_OWNER_NONE, MBOX_OWNER_FW, MBOX_OWNER_DRV }; /* mailbox owners */ enum { SGE_MAX_WR_LEN = 512, /* max WR size in bytes */ SGE_CTXT_SIZE = 24, /* size of SGE context */ SGE_NTIMERS = 6, /* # of interrupt holdoff timer values */ SGE_NCOUNTERS = 4, /* # of interrupt packet counter values */ SGE_MAX_IQ_SIZE = 65520, SGE_FLBUF_SIZES = 16, }; struct sge_qstat { /* data written to SGE queue status entries */ volatile __be32 qid; volatile __be16 cidx; volatile __be16 pidx; }; #define S_QSTAT_PIDX 0 #define M_QSTAT_PIDX 0xffff #define G_QSTAT_PIDX(x) (((x) >> S_QSTAT_PIDX) & M_QSTAT_PIDX) #define S_QSTAT_CIDX 16 #define M_QSTAT_CIDX 0xffff #define G_QSTAT_CIDX(x) (((x) >> S_QSTAT_CIDX) & M_QSTAT_CIDX) /* * Structure for last 128 bits of response descriptors */ struct rsp_ctrl { __be32 hdrbuflen_pidx; __be32 pldbuflen_qid; union { u8 type_gen; __be64 last_flit; } u; }; #define S_RSPD_NEWBUF 31 #define V_RSPD_NEWBUF(x) ((x) << S_RSPD_NEWBUF) #define F_RSPD_NEWBUF V_RSPD_NEWBUF(1U) #define S_RSPD_LEN 0 #define M_RSPD_LEN 0x7fffffff #define V_RSPD_LEN(x) ((x) << S_RSPD_LEN) #define G_RSPD_LEN(x) (((x) >> S_RSPD_LEN) & M_RSPD_LEN) #define S_RSPD_QID S_RSPD_LEN #define M_RSPD_QID M_RSPD_LEN #define V_RSPD_QID(x) V_RSPD_LEN(x) #define G_RSPD_QID(x) G_RSPD_LEN(x) #define S_RSPD_GEN 7 #define V_RSPD_GEN(x) ((x) << S_RSPD_GEN) #define F_RSPD_GEN V_RSPD_GEN(1U) #define S_RSPD_QOVFL 6 #define V_RSPD_QOVFL(x) ((x) << S_RSPD_QOVFL) #define F_RSPD_QOVFL V_RSPD_QOVFL(1U) #define S_RSPD_TYPE 4 #define M_RSPD_TYPE 0x3 #define V_RSPD_TYPE(x) ((x) << S_RSPD_TYPE) #define G_RSPD_TYPE(x) (((x) >> S_RSPD_TYPE) & M_RSPD_TYPE) /* Rx queue interrupt deferral fields: counter enable and timer index */ #define S_QINTR_CNT_EN 0 #define V_QINTR_CNT_EN(x) ((x) << S_QINTR_CNT_EN) #define F_QINTR_CNT_EN V_QINTR_CNT_EN(1U) #define S_QINTR_TIMER_IDX 1 #define M_QINTR_TIMER_IDX 0x7 #define V_QINTR_TIMER_IDX(x) ((x) << S_QINTR_TIMER_IDX) #define G_QINTR_TIMER_IDX(x) (((x) >> S_QINTR_TIMER_IDX) & M_QINTR_TIMER_IDX) /* # of pages a pagepod can hold without needing another pagepod */ #define PPOD_PAGES 4U struct pagepod { __be64 vld_tid_pgsz_tag_color; __be64 len_offset; __be64 rsvd; __be64 addr[PPOD_PAGES + 1]; }; #define S_PPOD_COLOR 0 #define M_PPOD_COLOR 0x3F #define V_PPOD_COLOR(x) ((x) << S_PPOD_COLOR) #define S_PPOD_TAG 6 #define M_PPOD_TAG 0xFFFFFF #define V_PPOD_TAG(x) ((x) << S_PPOD_TAG) #define G_PPOD_TAG(x) (((x) >> S_PPOD_TAG) & M_PPOD_TAG) #define S_PPOD_PGSZ 30 #define M_PPOD_PGSZ 0x3 #define V_PPOD_PGSZ(x) ((x) << S_PPOD_PGSZ) #define G_PPOD_PGSZ(x) (((x) >> S_PPOD_PGSZ) & M_PPOD_PGSZ) #define S_PPOD_TID 32 #define M_PPOD_TID 0xFFFFFF #define V_PPOD_TID(x) ((__u64)(x) << S_PPOD_TID) #define S_PPOD_VALID 56 #define V_PPOD_VALID(x) ((__u64)(x) << S_PPOD_VALID) #define F_PPOD_VALID V_PPOD_VALID(1ULL) #define S_PPOD_LEN 32 #define M_PPOD_LEN 0xFFFFFFFF #define V_PPOD_LEN(x) ((__u64)(x) << S_PPOD_LEN) #define S_PPOD_OFST 0 #define M_PPOD_OFST 0xFFFFFFFF #define V_PPOD_OFST(x) ((x) << S_PPOD_OFST) /* * Flash layout. */ #define FLASH_START(start) ((start) * SF_SEC_SIZE) #define FLASH_MAX_SIZE(nsecs) ((nsecs) * SF_SEC_SIZE) enum { /* * Various Expansion-ROM boot images, etc. */ FLASH_EXP_ROM_START_SEC = 0, FLASH_EXP_ROM_NSECS = 6, FLASH_EXP_ROM_START = FLASH_START(FLASH_EXP_ROM_START_SEC), FLASH_EXP_ROM_MAX_SIZE = FLASH_MAX_SIZE(FLASH_EXP_ROM_NSECS), /* * iSCSI Boot Firmware Table (iBFT) and other driver-related * parameters ... */ FLASH_IBFT_START_SEC = 6, FLASH_IBFT_NSECS = 1, FLASH_IBFT_START = FLASH_START(FLASH_IBFT_START_SEC), FLASH_IBFT_MAX_SIZE = FLASH_MAX_SIZE(FLASH_IBFT_NSECS), /* * Boot configuration data. */ FLASH_BOOTCFG_START_SEC = 7, FLASH_BOOTCFG_NSECS = 1, FLASH_BOOTCFG_START = FLASH_START(FLASH_BOOTCFG_START_SEC), FLASH_BOOTCFG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_BOOTCFG_NSECS), /* * Location of firmware image in FLASH. */ FLASH_FW_START_SEC = 8, FLASH_FW_NSECS = 16, FLASH_FW_START = FLASH_START(FLASH_FW_START_SEC), FLASH_FW_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FW_NSECS), /* * Location of bootstrap firmware image in FLASH. */ FLASH_FWBOOTSTRAP_START_SEC = 27, FLASH_FWBOOTSTRAP_NSECS = 1, FLASH_FWBOOTSTRAP_START = FLASH_START(FLASH_FWBOOTSTRAP_START_SEC), FLASH_FWBOOTSTRAP_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FWBOOTSTRAP_NSECS), /* * iSCSI persistent/crash information. */ FLASH_ISCSI_CRASH_START_SEC = 29, FLASH_ISCSI_CRASH_NSECS = 1, FLASH_ISCSI_CRASH_START = FLASH_START(FLASH_ISCSI_CRASH_START_SEC), FLASH_ISCSI_CRASH_MAX_SIZE = FLASH_MAX_SIZE(FLASH_ISCSI_CRASH_NSECS), /* * FCoE persistent/crash information. */ FLASH_FCOE_CRASH_START_SEC = 30, FLASH_FCOE_CRASH_NSECS = 1, FLASH_FCOE_CRASH_START = FLASH_START(FLASH_FCOE_CRASH_START_SEC), FLASH_FCOE_CRASH_MAX_SIZE = FLASH_MAX_SIZE(FLASH_FCOE_CRASH_NSECS), /* * Location of Firmware Configuration File in FLASH. */ FLASH_CFG_START_SEC = 31, FLASH_CFG_NSECS = 1, FLASH_CFG_START = FLASH_START(FLASH_CFG_START_SEC), FLASH_CFG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_CFG_NSECS), /* * We don't support FLASH devices which can't support the full * standard set of sections which we need for normal operations. */ FLASH_MIN_SIZE = FLASH_CFG_START + FLASH_CFG_MAX_SIZE, /* - * Sectors 32-63 are reserved for FLASH failover. + * Sectors 32-63 for CUDBG. */ + FLASH_CUDBG_START_SEC = 32, + FLASH_CUDBG_NSECS = 32, + FLASH_CUDBG_START = FLASH_START(FLASH_CUDBG_START_SEC), + FLASH_CUDBG_MAX_SIZE = FLASH_MAX_SIZE(FLASH_CUDBG_NSECS), + + /* + * Size of defined FLASH regions. + */ + FLASH_END_SEC = 64, }; #undef FLASH_START #undef FLASH_MAX_SIZE #define S_SGE_TIMESTAMP 0 #define M_SGE_TIMESTAMP 0xfffffffffffffffULL #define V_SGE_TIMESTAMP(x) ((__u64)(x) << S_SGE_TIMESTAMP) #define G_SGE_TIMESTAMP(x) (((__u64)(x) >> S_SGE_TIMESTAMP) & M_SGE_TIMESTAMP) #endif /* __T4_HW_H */ Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg.h (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg.h (revision 322022) @@ -0,0 +1,474 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +/* + * Chelsio Unified Debug Interface header file. + * Version 1.1 + */ +#ifndef _CUDBG_IF_H_ +#define _CUDBG_IF_H_ + +#ifdef __GNUC__ +#define ATTRIBUTE_UNUSED __attribute__ ((unused)) +#else +#define ATTRIBUTE_UNUSED +#endif + +#if defined(CONFIG_CUDBG_DEBUG) +#define cudbg_debug(pdbg_init, format, ...) do {\ + pdbg_init->print(format, ##__VA_ARGS__); \ +} while (0) +#else +#define cudbg_debug(pdbg_init, format, ...) do { } while (0) +#endif + +#define OUT +#define IN +#define INOUT + +/* Error codes */ + +#define CUDBG_STATUS_SUCCESS 0 +#define CUDBG_STATUS_NOSPACE -2 +#define CUDBG_STATUS_FLASH_WRITE_FAIL -3 +#define CUDBG_STATUS_FLASH_READ_FAIL -4 +#define CUDBG_STATUS_UNDEFINED_OUT_BUF -5 +#define CUDBG_STATUS_UNDEFINED_CBFN -6 +#define CUDBG_STATUS_UNDEFINED_PRINTF_CBFN -7 +#define CUDBG_STATUS_ADAP_INVALID -8 +#define CUDBG_STATUS_FLASH_EMPTY -9 +#define CUDBG_STATUS_NO_ADAPTER -10 +#define CUDBG_STATUS_NO_SIGNATURE -11 +#define CUDBG_STATUS_MULTIPLE_REG -12 +#define CUDBG_STATUS_UNREGISTERED -13 +#define CUDBG_STATUS_UNDEFINED_ENTITY -14 +#define CUDBG_STATUS_REG_FAIlED -15 +#define CUDBG_STATUS_DEVLOG_FAILED -16 +#define CUDBG_STATUS_SMALL_BUFF -17 +#define CUDBG_STATUS_CHKSUM_MISSMATCH -18 +#define CUDBG_STATUS_NO_SCRATCH_MEM -19 +#define CUDBG_STATUS_OUTBUFF_OVERFLOW -20 +#define CUDBG_STATUS_INVALID_BUFF -21 /* Invalid magic */ +#define CUDBG_STATUS_FILE_OPEN_FAIL -22 +#define CUDBG_STATUS_DEVLOG_INT_FAIL -23 +#define CUDBG_STATUS_ENTITY_NOT_FOUND -24 +#define CUDBG_STATUS_DECOMPRESS_FAIL -25 +#define CUDBG_STATUS_BUFFER_SHORT -26 +#define CUDBG_METADATA_VERSION_MISMATCH -27 +#define CUDBG_STATUS_NOT_IMPLEMENTED -28 +#define CUDBG_SYSTEM_ERROR -29 +#define CUDBG_STATUS_MMAP_FAILED -30 +#define CUDBG_STATUS_FILE_WRITE_FAILED -31 +#define CUDBG_STATUS_CCLK_NOT_DEFINED -32 +#define CUDBG_STATUS_FLASH_FULL -33 +#define CUDBG_STATUS_SECTOR_EMPTY -34 +#define CUDBG_STATUS_ENTITY_NOT_REQUESTED -35 +#define CUDBG_STATUS_NOT_SUPPORTED -36 +#define CUDBG_STATUS_FILE_READ_FAILED -37 +#define CUDBG_STATUS_CORRUPTED -38 +#define CUDBG_STATUS_INVALID_INDEX -39 + +#define CUDBG_MAJOR_VERSION 1 +#define CUDBG_MINOR_VERSION 14 +#define CUDBG_BUILD_VERSION 0 + +#define CUDBG_FILE_NAME_LEN 256 +#define CUDBG_DIR_NAME_LEN 256 +#define CUDBG_MAX_BITMAP_LEN 16 + +static char ATTRIBUTE_UNUSED * err_msg[] = { + "Success", + "Unknown", + "No space", + "Flash write fail", + "Flash read fail", + "Undefined out buf", + "Callback function undefined", + "Print callback function undefined", + "ADAP invalid", + "Flash empty", + "No adapter", + "No signature", + "Multiple registration", + "Unregistered", + "Undefined entity", + "Reg failed", + "Devlog failed", + "Small buff", + "Checksum mismatch", + "No scratch memory", + "Outbuff overflow", + "Invalid buffer", + "File open fail", + "Devlog int fail", + "Entity not found", + "Decompress fail", + "Buffer short", + "Version mismatch", + "Not implemented", + "System error", + "Mmap failed", + "File write failed", + "cclk not defined", + "Flash full", + "Sector empty", + "Entity not requested", + "Not supported", + "File read fail", + "Corrupted", + "Invalid Index" +}; + +enum CUDBG_DBG_ENTITY_TYPE { + CUDBG_ALL = 0, + CUDBG_REG_DUMP = 1, + CUDBG_DEV_LOG = 2, + CUDBG_CIM_LA = 3, + CUDBG_CIM_MA_LA = 4, + CUDBG_CIM_QCFG = 5, + CUDBG_CIM_IBQ_TP0 = 6, + CUDBG_CIM_IBQ_TP1 = 7, + CUDBG_CIM_IBQ_ULP = 8, + CUDBG_CIM_IBQ_SGE0 = 9, + CUDBG_CIM_IBQ_SGE1 = 10, + CUDBG_CIM_IBQ_NCSI = 11, + CUDBG_CIM_OBQ_ULP0 = 12, + CUDBG_CIM_OBQ_ULP1 = 13, + CUDBG_CIM_OBQ_ULP2 = 14, + CUDBG_CIM_OBQ_ULP3 = 15, + CUDBG_CIM_OBQ_SGE = 16, + CUDBG_CIM_OBQ_NCSI = 17, + CUDBG_EDC0 = 18, + CUDBG_EDC1 = 19, + CUDBG_MC0 = 20, + CUDBG_MC1 = 21, + CUDBG_RSS = 22, + CUDBG_RSS_PF_CONF = 23, + CUDBG_RSS_KEY = 24, + CUDBG_RSS_VF_CONF = 25, + CUDBG_RSS_CONF = 26, + CUDBG_PATH_MTU = 27, + CUDBG_SW_STATE = 28, + CUDBG_WTP = 29, + CUDBG_PM_STATS = 30, + CUDBG_HW_SCHED = 31, + CUDBG_TCP_STATS = 32, + CUDBG_TP_ERR_STATS = 33, + CUDBG_FCOE_STATS = 34, + CUDBG_RDMA_STATS = 35, + CUDBG_TP_INDIRECT = 36, + CUDBG_SGE_INDIRECT = 37, + CUDBG_CPL_STATS = 38, + CUDBG_DDP_STATS = 39, + CUDBG_WC_STATS = 40, + CUDBG_ULPRX_LA = 41, + CUDBG_LB_STATS = 42, + CUDBG_TP_LA = 43, + CUDBG_MEMINFO = 44, + CUDBG_CIM_PIF_LA = 45, + CUDBG_CLK = 46, + CUDBG_CIM_OBQ_RXQ0 = 47, + CUDBG_CIM_OBQ_RXQ1 = 48, + CUDBG_MAC_STATS = 49, + CUDBG_PCIE_INDIRECT = 50, + CUDBG_PM_INDIRECT = 51, + CUDBG_FULL = 52, + CUDBG_TX_RATE = 53, + CUDBG_TID_INFO = 54, + CUDBG_PCIE_CONFIG = 55, + CUDBG_DUMP_CONTEXT = 56, + CUDBG_MPS_TCAM = 57, + CUDBG_VPD_DATA = 58, + CUDBG_LE_TCAM = 59, + CUDBG_CCTRL = 60, + CUDBG_MA_INDIRECT = 61, + CUDBG_ULPTX_LA = 62, + CUDBG_EXT_ENTITY = 63, + CUDBG_UP_CIM_INDIRECT = 64, + CUDBG_PBT_TABLE = 65, + CUDBG_MBOX_LOG = 66, + CUDBG_HMA_INDIRECT = 67, + CUDBG_MAX_ENTITY = 68, +}; + +#define ENTITY_FLAG_NULL 0 +#define ENTITY_FLAG_REGISTER 1 +#define ENTITY_FLAG_BINARY 2 +#define ENTITY_FLAG_FW_NO_ATTACH 3 + +/* file_name matches Linux cxgb4 debugfs entry names. */ +struct el {char *name; char *file_name; int bit; u32 flag; }; +static struct el ATTRIBUTE_UNUSED entity_list[] = { + {"all", "all", CUDBG_ALL, ENTITY_FLAG_NULL}, + {"regdump", "regdump", CUDBG_REG_DUMP, 1 << ENTITY_FLAG_REGISTER}, + /* {"reg", CUDBG_REG_DUMP},*/ + {"devlog", "devlog", CUDBG_DEV_LOG, ENTITY_FLAG_NULL}, + {"cimla", "cim_la", CUDBG_CIM_LA, ENTITY_FLAG_NULL}, + {"cimmala", "cim_ma_la", CUDBG_CIM_MA_LA, ENTITY_FLAG_NULL}, + {"cimqcfg", "cim_qcfg", CUDBG_CIM_QCFG, ENTITY_FLAG_NULL}, + {"ibqtp0", "ibq_tp0", CUDBG_CIM_IBQ_TP0, ENTITY_FLAG_NULL}, + {"ibqtp1", "ibq_tp1", CUDBG_CIM_IBQ_TP1, ENTITY_FLAG_NULL}, + {"ibqulp", "ibq_ulp", CUDBG_CIM_IBQ_ULP, ENTITY_FLAG_NULL}, + {"ibqsge0", "ibq_sge0", CUDBG_CIM_IBQ_SGE0, ENTITY_FLAG_NULL}, + {"ibqsge1", "ibq_sge1", CUDBG_CIM_IBQ_SGE1, ENTITY_FLAG_NULL}, + {"ibqncsi", "ibq_ncsi", CUDBG_CIM_IBQ_NCSI, ENTITY_FLAG_NULL}, + {"obqulp0", "obq_ulp0", CUDBG_CIM_OBQ_ULP0, ENTITY_FLAG_NULL}, + /* {"cimobqulp1", CUDBG_CIM_OBQ_ULP1},*/ + {"obqulp1", "obq_ulp1", CUDBG_CIM_OBQ_ULP1, ENTITY_FLAG_NULL}, + {"obqulp2", "obq_ulp2", CUDBG_CIM_OBQ_ULP2, ENTITY_FLAG_NULL}, + {"obqulp3", "obq_ulp3", CUDBG_CIM_OBQ_ULP3, ENTITY_FLAG_NULL}, + {"obqsge", "obq_sge", CUDBG_CIM_OBQ_SGE, ENTITY_FLAG_NULL}, + {"obqncsi", "obq_ncsi", CUDBG_CIM_OBQ_NCSI, ENTITY_FLAG_NULL}, + {"edc0", "edc0", CUDBG_EDC0, (1 << ENTITY_FLAG_BINARY)}, + {"edc1", "edc1", CUDBG_EDC1, (1 << ENTITY_FLAG_BINARY)}, + {"mc0", "mc0", CUDBG_MC0, (1 << ENTITY_FLAG_BINARY)}, + {"mc1", "mc1", CUDBG_MC1, (1 << ENTITY_FLAG_BINARY)}, + {"rss", "rss", CUDBG_RSS, ENTITY_FLAG_NULL}, + {"rss_pf_config", "rss_pf_config", CUDBG_RSS_PF_CONF, ENTITY_FLAG_NULL}, + {"rss_key", "rss_key", CUDBG_RSS_KEY, ENTITY_FLAG_NULL}, + {"rss_vf_config", "rss_vf_config", CUDBG_RSS_VF_CONF, ENTITY_FLAG_NULL}, + {"rss_config", "rss_config", CUDBG_RSS_CONF, ENTITY_FLAG_NULL}, + {"pathmtu", "path_mtus", CUDBG_PATH_MTU, ENTITY_FLAG_NULL}, + {"swstate", "sw_state", CUDBG_SW_STATE, ENTITY_FLAG_NULL}, + {"wtp", "wtp", CUDBG_WTP, ENTITY_FLAG_NULL}, + {"pmstats", "pm_stats", CUDBG_PM_STATS, ENTITY_FLAG_NULL}, + {"hwsched", "hw_sched", CUDBG_HW_SCHED, ENTITY_FLAG_NULL}, + {"tcpstats", "tcp_stats", CUDBG_TCP_STATS, ENTITY_FLAG_NULL}, + {"tperrstats", "tp_err_stats", CUDBG_TP_ERR_STATS, ENTITY_FLAG_NULL}, + {"fcoestats", "fcoe_stats", CUDBG_FCOE_STATS, ENTITY_FLAG_NULL}, + {"rdmastats", "rdma_stats", CUDBG_RDMA_STATS, ENTITY_FLAG_NULL}, + {"tpindirect", "tp_indirect", CUDBG_TP_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"sgeindirect", "sge_indirect", CUDBG_SGE_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"cplstats", "cpl_stats", CUDBG_CPL_STATS, ENTITY_FLAG_NULL}, + {"ddpstats", "ddp_stats", CUDBG_DDP_STATS, ENTITY_FLAG_NULL}, + {"wcstats", "wc_stats", CUDBG_WC_STATS, ENTITY_FLAG_NULL}, + {"ulprxla", "ulprx_la", CUDBG_ULPRX_LA, ENTITY_FLAG_NULL}, + {"lbstats", "lb_stats", CUDBG_LB_STATS, ENTITY_FLAG_NULL}, + {"tpla", "tp_la", CUDBG_TP_LA, ENTITY_FLAG_NULL}, + {"meminfo", "meminfo", CUDBG_MEMINFO, ENTITY_FLAG_NULL}, + {"cimpifla", "cim_pif_la", CUDBG_CIM_PIF_LA, ENTITY_FLAG_NULL}, + {"clk", "clk", CUDBG_CLK, ENTITY_FLAG_NULL}, + {"obq_sge_rx_q0", "obq_sge_rx_q0", CUDBG_CIM_OBQ_RXQ0, + ENTITY_FLAG_NULL}, + {"obq_sge_rx_q1", "obq_sge_rx_q1", CUDBG_CIM_OBQ_RXQ1, + ENTITY_FLAG_NULL}, + {"macstats", "mac_stats", CUDBG_MAC_STATS, ENTITY_FLAG_NULL}, + {"pcieindirect", "pcie_indirect", CUDBG_PCIE_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"pmindirect", "pm_indirect", CUDBG_PM_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"full", "full", CUDBG_FULL, ENTITY_FLAG_NULL}, + {"txrate", "tx_rate", CUDBG_TX_RATE, ENTITY_FLAG_NULL}, + {"tidinfo", "tids", CUDBG_TID_INFO, ENTITY_FLAG_NULL | + (1 << ENTITY_FLAG_FW_NO_ATTACH)}, + {"pcieconfig", "pcie_config", CUDBG_PCIE_CONFIG, ENTITY_FLAG_NULL}, + {"dumpcontext", "dump_context", CUDBG_DUMP_CONTEXT, ENTITY_FLAG_NULL}, + {"mpstcam", "mps_tcam", CUDBG_MPS_TCAM, ENTITY_FLAG_NULL}, + {"vpddata", "vpd_data", CUDBG_VPD_DATA, ENTITY_FLAG_NULL}, + {"letcam", "le_tcam", CUDBG_LE_TCAM, ENTITY_FLAG_NULL}, + {"cctrl", "cctrl", CUDBG_CCTRL, ENTITY_FLAG_NULL}, + {"maindirect", "ma_indirect", CUDBG_MA_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"ulptxla", "ulptx_la", CUDBG_ULPTX_LA, ENTITY_FLAG_NULL}, + {"extentity", "ext_entity", CUDBG_EXT_ENTITY, ENTITY_FLAG_NULL}, + {"upcimindirect", "up_cim_indirect", CUDBG_UP_CIM_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, + {"pbttables", "pbt_tables", CUDBG_PBT_TABLE, ENTITY_FLAG_NULL}, + {"mboxlog", "mboxlog", CUDBG_MBOX_LOG, ENTITY_FLAG_NULL}, + {"hmaindirect", "hma_indirect", CUDBG_HMA_INDIRECT, + 1 << ENTITY_FLAG_REGISTER}, +}; + +typedef int (*cudbg_print_cb) (char *str, ...); + +struct cudbg_init_hdr { + u8 major_ver; + u8 minor_ver; + u8 build_ver; + u8 res; + u16 init_struct_size; +}; + +struct cudbg_flash_hdr { + u32 signature; + u8 major_ver; + u8 minor_ver; + u8 build_ver; + u8 res; + u64 timestamp; + u64 time_res; + u32 hdr_len; + u32 data_len; + u32 hdr_flags; + u32 sec_seq_no; + u32 reserved[22]; +}; + +struct cudbg_param { + u16 param_type; + u16 reserved; + union { + struct { + u32 memtype; /* which memory (EDC0, EDC1, MC) */ + u32 start; /* start of log in firmware memory */ + u32 size; /* size of log */ + } devlog_param; + struct { + struct mbox_cmd_log *log; + u16 mbox_cmds; + } mboxlog_param; + struct { + u8 caller_string[100]; + u8 os_type; + } sw_state_param; + u64 time; + u8 tcb_bit_param; + void *adap; + void *access_lock; + } u; +}; + +/* params for tcb_bit_param */ +#define CUDBG_TCB_BRIEF_PARAM 0x1 +#define CUDBG_TCB_FROM_CARD_PARAM 0x2 +#define CUDBG_TCB_AS_SCB_PARAM 0x4 + +/* + * * What is OFFLINE_VIEW_ONLY mode? + * + * cudbg frame work will be used only to interpret previously collected + * data store in a file (i.e NOT hw flash) + */ + +struct cudbg_init { + struct cudbg_init_hdr header; + struct adapter *adap; /* Pointer to adapter structure + with filled fields */ + cudbg_print_cb print; /* Platform dependent print + function */ + u32 verbose:1; /* Turn on verbose print */ + u32 use_flash:1; /* Use flash to collect or view + debug */ + u32 full_mode:1; /* If set, cudbg will pull in + common code */ + u32 no_compress:1; /* Dont compress will storing + the collected debug */ + u32 info:1; /* Show just the info, Dont + interpret */ + u32 reserved:27; + u8 dbg_bitmap[CUDBG_MAX_BITMAP_LEN]; + /* Bit map to select the dbg + data type to be collected + or viewed */ +}; + + +/********************************* Helper functions *************************/ +static inline void set_dbg_bitmap(u8 *bitmap, enum CUDBG_DBG_ENTITY_TYPE type) +{ + int index = type / 8; + int bit = type % 8; + + bitmap[index] |= (1 << bit); +} + +static inline void reset_dbg_bitmap(u8 *bitmap, enum CUDBG_DBG_ENTITY_TYPE type) +{ + int index = type / 8; + int bit = type % 8; + + bitmap[index] &= ~(1 << bit); +} + +/********************************* End of Helper functions + * *************************/ + +/* API Prototypes */ + +/** + * cudbg_alloc_handle - Allocates and initializes a handle that represents + * cudbg state. Needs to called first before calling any other function. + * + * returns a pointer to memory that has a cudbg_init structure at the begining + * and enough space after that for internal book keeping. + */ + +void *cudbg_alloc_handle(void); +static inline struct cudbg_init *cudbg_get_init(void *handle) +{ + return (handle); +} + +/** + * cudbg_collect - Collect and store debug information. + * ## Parameters ## + * @handle : A pointer returned by cudbg_alloc_handle. + * @outbuf : pointer to output buffer, to store the collected information + * or to use it as a scratch buffer in case HW flash is used to + * store the debug information. + * @outbuf_size : Size of output buffer. + * ## Return ## + * If the function succeeds, the return value will be size of debug information + * collected and stored. + * -ve value represent error. + */ +int cudbg_collect(void *handle, void *outbuf, u32 *outbuf_size); + +/** + * cudbg_free_handle - Release cudbg resources. + * ## Parameters ## + * @handle : A pointer returned by cudbg_alloc_handle. + */ + +void cudbg_free_handle(IN void *handle); + +/** + * cudbg_read_flash_data - Read cudbg “flashâ€� header from adapter flash. + * This will be used by the consumer mainly to + * know the size of the data in flash. + * ## Parameters ## + * @handle : A pointer returned by cudbg_hello. + * @data : A pointer to data/header buffer + */ + +int cudbg_read_flash_details(void *handle, struct cudbg_flash_hdr *data); + +/** + * cudbg_read_flash_data - Read cudbg dump contents stored in flash. + * ## Parameters ## + * @handle : A pointer returned by cudbg_hello. + * @data_buf : A pointer to data buffer. + * @data_buf_size : Data buffer size. + */ + +int cudbg_read_flash_data(void *handle, void *data_buf, u32 data_buf_size); + +#endif /* _CUDBG_IF_H_ */ Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_common.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_common.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_common.c (revision 322022) @@ -0,0 +1,96 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "common/common.h" +#include "cudbg.h" +#include "cudbg_lib_common.h" + +int get_scratch_buff(struct cudbg_buffer *pdbg_buff, u32 size, + struct cudbg_buffer *pscratch_buff) +{ + u32 scratch_offset; + int rc = 0; + + scratch_offset = pdbg_buff->size - size; + + if (pdbg_buff->offset > (int)scratch_offset || pdbg_buff->size < size) { + rc = CUDBG_STATUS_NO_SCRATCH_MEM; + goto err; + } else { + pscratch_buff->data = (char *)pdbg_buff->data + scratch_offset; + pscratch_buff->offset = 0; + pscratch_buff->size = size; + pdbg_buff->size -= size; + } + +err: + return rc; +} + +void release_scratch_buff(struct cudbg_buffer *pscratch_buff, + struct cudbg_buffer *pdbg_buff) +{ + pdbg_buff->size += pscratch_buff->size; + /* Reset the used buffer to zero. + * If we dont do this, then it will effect the ext entity logic. + */ + memset(pscratch_buff->data, 0, pscratch_buff->size); + pscratch_buff->data = NULL; + pscratch_buff->offset = 0; + pscratch_buff->size = 0; +} + +static inline void init_cudbg_hdr(struct cudbg_init_hdr *hdr) +{ + hdr->major_ver = CUDBG_MAJOR_VERSION; + hdr->minor_ver = CUDBG_MINOR_VERSION; + hdr->build_ver = CUDBG_BUILD_VERSION; + hdr->init_struct_size = sizeof(struct cudbg_init); +} + +void * +cudbg_alloc_handle(void) +{ + struct cudbg_private *handle; + + handle = malloc(sizeof(*handle), M_CXGBE, M_ZERO | M_WAITOK); + init_cudbg_hdr(&handle->dbg_init.header); + + return (handle); +} + +void +cudbg_free_handle(void *handle) +{ + + free(handle, M_CXGBE); +} Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_common.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_entity.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_entity.h (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_entity.h (revision 322022) @@ -0,0 +1,909 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef __CUDBG_ENTITY_H__ +#define __CUDBG_ENTITY_H__ + +#ifdef __GNUC__ +#define ATTRIBUTE_UNUSED __attribute__ ((unused)) +#else +#define ATTRIBUTE_UNUSED +#endif + +#define MC0_FLAG 1 +#define MC1_FLAG 2 +#define EDC0_FLAG 3 +#define EDC1_FLAG 4 + +#define NUM_PCIE_CONFIG_REGS 0x61 +#define CUDBG_CTXT_SIZE_BYTES 24 +#define CUDBG_MAX_INGRESS_QIDS 65536 +#define CUDBG_MAX_FL_QIDS 2048 +#define CUDBG_MAX_CNM_QIDS 1024 +#define CUDBG_LOWMEM_MAX_CTXT_QIDS 256 +#define ETH_ALEN 6 +#define CUDBG_MAX_RPLC_SIZE 128 +#define CUDBG_NUM_REQ_REGS 17 +#define CUDBG_MAX_TCAM_TID 0x800 +#define CUDBG_NUM_ULPTX 11 +#define CUDBG_NUM_ULPTX_READ 512 + +#define SN_REG_ADDR 0x183f +#define BN_REG_ADDR 0x1819 +#define NA_REG_ADDR 0x185a +#define MN_REG_ADDR 0x1803 + +#define A_MPS_VF_RPLCT_MAP0 0x1111c +#define A_MPS_VF_RPLCT_MAP1 0x11120 +#define A_MPS_VF_RPLCT_MAP2 0x11124 +#define A_MPS_VF_RPLCT_MAP3 0x11128 +#define A_MPS_VF_RPLCT_MAP4 0x11300 +#define A_MPS_VF_RPLCT_MAP5 0x11304 +#define A_MPS_VF_RPLCT_MAP6 0x11308 +#define A_MPS_VF_RPLCT_MAP7 0x1130c + +#define PORT_TYPE_ADDR 0x1869 +#define PORT_TYPE_LEN 8 + +/* For T6 */ +#define SN_T6_ADDR 0x83f +#define BN_T6_ADDR 0x819 +#define NA_T6_ADDR 0x85a +#define MN_T6_ADDR 0x803 + +#define SN_MAX_LEN 24 +#define BN_MAX_LEN 16 +#define NA_MAX_LEN 12 +#define MN_MAX_LEN 16 +#define MAX_VPD_DATA_LEN 32 + +#define VPD_VER_ADDR 0x18c7 +#define VPD_VER_LEN 2 +#define SCFG_VER_ADDR 0x06 +#define SCFG_VER_LEN 4 + +#define CUDBG_CIM_BUSY_BIT (1 << 17) + +#define CUDBG_CHAC_PBT_ADDR 0x2800 +#define CUDBG_CHAC_PBT_LRF 0x3000 +#define CUDBG_CHAC_PBT_DATA 0x3800 +#define CUDBG_PBT_DYNAMIC_ENTRIES 8 +#define CUDBG_PBT_STATIC_ENTRIES 16 +#define CUDBG_LRF_ENTRIES 8 +#define CUDBG_PBT_DATA_ENTRIES 512 + +#define CUDBG_ENTITY_SIGNATURE 0xCCEDB001 +#define CUDBG_TID_INFO_REV 1 +#define CUDBG_MAC_STATS_REV 1 + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(_a) (sizeof((_a)) / sizeof((_a)[0])) +#endif + +struct cudbg_pbt_tables { + u32 pbt_dynamic[CUDBG_PBT_DYNAMIC_ENTRIES]; + u32 pbt_static[CUDBG_PBT_STATIC_ENTRIES]; + u32 lrf_table[CUDBG_LRF_ENTRIES]; + u32 pbt_data[CUDBG_PBT_DATA_ENTRIES]; +}; + +struct card_mem { + u16 size_mc0; + u16 size_mc1; + u16 size_edc0; + u16 size_edc1; + u16 mem_flag; + u16 res; +}; + +struct rss_pf_conf { + u32 rss_pf_map; + u32 rss_pf_mask; + u32 rss_pf_config; +}; + +struct cudbg_ch_cntxt { + uint32_t cntxt_type; + uint32_t cntxt_id; + uint32_t data[SGE_CTXT_SIZE / 4]; +}; + +struct cudbg_tcam { + u32 filter_start; + u32 server_start; + u32 clip_start; + u32 routing_start; + u32 tid_hash_base; + u32 max_tid; +}; + +#if 0 +struct cudbg_mbox_log { + struct mbox_cmd entry; + u32 hi[MBOX_LEN / 8]; + u32 lo[MBOX_LEN / 8]; +}; +#endif + +struct cudbg_tid_data { + u32 tid; + u32 dbig_cmd; + u32 dbig_conf; + u32 dbig_rsp_stat; + u32 data[CUDBG_NUM_REQ_REGS]; +}; + +struct cudbg_cntxt_field { + char *name; + u32 start_bit; + u32 end_bit; + u32 shift; + u32 islog2; +}; + +struct cudbg_mps_tcam { + u64 mask; + u32 rplc[8]; + u32 idx; + u32 cls_lo; + u32 cls_hi; + u32 rplc_size; + u32 vniy; + u32 vnix; + u32 dip_hit; + u32 vlan_vld; + u32 repli; + u16 ivlan; + u8 addr[ETH_ALEN]; + u8 lookup_type; + u8 port_num; + u8 reserved[2]; +}; + +struct rss_vf_conf { + u32 rss_vf_vfl; + u32 rss_vf_vfh; +}; + +struct rss_config { + u32 tp_rssconf; /* A_TP_RSS_CONFIG */ + u32 tp_rssconf_tnl; /* A_TP_RSS_CONFIG_TNL */ + u32 tp_rssconf_ofd; /* A_TP_RSS_CONFIG_OFD */ + u32 tp_rssconf_syn; /* A_TP_RSS_CONFIG_SYN */ + u32 tp_rssconf_vrt; /* A_TP_RSS_CONFIG_VRT */ + u32 tp_rssconf_cng; /* A_TP_RSS_CONFIG_CNG */ + u32 chip; +}; + +struct struct_pm_stats { + u32 tx_cnt[T6_PM_NSTATS]; + u32 rx_cnt[T6_PM_NSTATS]; + u64 tx_cyc[T6_PM_NSTATS]; + u64 rx_cyc[T6_PM_NSTATS]; +}; + +struct struct_hw_sched { + u32 kbps[NTX_SCHED]; + u32 ipg[NTX_SCHED]; + u32 pace_tab[NTX_SCHED]; + u32 mode; + u32 map; +}; + +struct struct_tcp_stats { + struct tp_tcp_stats v4, v6; +}; + +struct struct_tp_err_stats { + struct tp_err_stats stats; + u32 nchan; +}; + +struct struct_tp_fcoe_stats { + struct tp_fcoe_stats stats[4]; + u32 nchan; +}; + +struct struct_mac_stats { + u32 port_count; + struct port_stats stats[4]; +}; + +struct struct_mac_stats_rev1 { + struct cudbg_ver_hdr ver_hdr; + u32 port_count; + u32 reserved; + struct port_stats stats[4]; +}; + +struct struct_tp_cpl_stats { + struct tp_cpl_stats stats; + u32 nchan; +}; + +struct struct_wc_stats { + u32 wr_cl_success; + u32 wr_cl_fail; +}; + +struct struct_ulptx_la { + u32 rdptr[CUDBG_NUM_ULPTX]; + u32 wrptr[CUDBG_NUM_ULPTX]; + u32 rddata[CUDBG_NUM_ULPTX]; + u32 rd_data[CUDBG_NUM_ULPTX][CUDBG_NUM_ULPTX_READ]; +}; + +struct struct_ulprx_la { + u32 data[ULPRX_LA_SIZE * 8]; + u32 size; +}; + +struct struct_cim_qcfg { + u8 chip; + u16 base[CIM_NUM_IBQ + CIM_NUM_OBQ_T5]; + u16 size[CIM_NUM_IBQ + CIM_NUM_OBQ_T5]; + u16 thres[CIM_NUM_IBQ]; + u32 obq_wr[2 * CIM_NUM_OBQ_T5]; + u32 stat[4 * (CIM_NUM_IBQ + CIM_NUM_OBQ_T5)]; +}; + +enum region_index { + REGN_DBQ_CONTEXS_IDX, + REGN_IMSG_CONTEXTS_IDX, + REGN_FLM_CACHE_IDX, + REGN_TCBS_IDX, + REGN_PSTRUCT_IDX, + REGN_TIMERS_IDX, + REGN_RX_FL_IDX, + REGN_TX_FL_IDX, + REGN_PSTRUCT_FL_IDX, + REGN_TX_PAYLOAD_IDX, + REGN_RX_PAYLOAD_IDX, + REGN_LE_HASH_IDX, + REGN_ISCSI_IDX, + REGN_TDDP_IDX, + REGN_TPT_IDX, + REGN_STAG_IDX, + REGN_RQ_IDX, + REGN_RQUDP_IDX, + REGN_PBL_IDX, + REGN_TXPBL_IDX, + REGN_DBVFIFO_IDX, + REGN_ULPRX_STATE_IDX, + REGN_ULPTX_STATE_IDX, +#ifndef __NO_DRIVER_OCQ_SUPPORT__ + REGN_ON_CHIP_Q_IDX, +#endif +}; + +static const char * const region[] = { + "DBQ contexts:", "IMSG contexts:", "FLM cache:", "TCBs:", + "Pstructs:", "Timers:", "Rx FL:", "Tx FL:", "Pstruct FL:", + "Tx payload:", "Rx payload:", "LE hash:", "iSCSI region:", + "TDDP region:", "TPT region:", "STAG region:", "RQ region:", + "RQUDP region:", "PBL region:", "TXPBL region:", + "DBVFIFO region:", "ULPRX state:", "ULPTX state:", +#ifndef __NO_DRIVER_OCQ_SUPPORT__ + "On-chip queues:" +#endif +}; + +/* Info relative to memory region (i.e. wrt 0). */ +struct struct_region_info { + bool exist; /* Does region exists in current memory region? */ + u32 start; /* Start wrt 0 */ + u32 end; /* End wrt 0 */ +}; + +struct struct_port_usage { + u32 id; + u32 used; + u32 alloc; +}; + +struct struct_lpbk_usage { + u32 id; + u32 used; + u32 alloc; +}; + +struct struct_mem_desc { + u32 base; + u32 limit; + u32 idx; +}; + +enum string_size_units { + STRING_UNITS_10, /* use powers of 10^3 (standard SI) */ + STRING_UNITS_2, /* use binary powers of 2^10 */ +}; + +struct struct_meminfo { + struct struct_mem_desc avail[4]; + struct struct_mem_desc mem[ARRAY_SIZE(region) + 3]; + u32 avail_c; + u32 mem_c; + u32 up_ram_lo; + u32 up_ram_hi; + u32 up_extmem2_lo; + u32 up_extmem2_hi; + u32 rx_pages_data[3]; + u32 tx_pages_data[4]; + u32 p_structs; + struct struct_port_usage port_data[4]; + u32 port_used[4]; + u32 port_alloc[4]; + u32 loopback_used[NCHAN]; + u32 loopback_alloc[NCHAN]; +}; + +#ifndef __GNUC__ +#pragma warning(disable : 4200) +#endif + +struct struct_lb_stats { + int nchan; + struct lb_port_stats s[0]; +}; + +struct struct_clk_info { + u64 retransmit_min; + u64 retransmit_max; + u64 persist_timer_min; + u64 persist_timer_max; + u64 keepalive_idle_timer; + u64 keepalive_interval; + u64 initial_srtt; + u64 finwait2_timer; + u32 dack_timer; + u32 res; + u32 cclk_ps; + u32 tre; + u32 dack_re; + char core_clk_period[32]; + char tp_timer_tick[32]; + char tcp_tstamp_tick[32]; + char dack_tick[32]; +}; + +struct cim_pif_la { + int size; + u8 data[0]; +}; + +struct struct_tp_la { + u32 size; + u32 mode; + u8 data[0]; +}; + +struct field_desc { + const char *name; + u32 start; + u32 width; +}; + +struct tp_mib_type { + char *key; + u32 addr; + u32 value; +}; + +struct wtp_type_0 { + u32 sop; + u32 eop; +}; + +struct wtp_type_1 { + u32 sop[2]; + u32 eop[2]; +}; + +struct wtp_type_2 { + u32 sop[4]; + u32 eop[4]; +}; + +struct wtp_type_3 { + u32 sop[4]; + u32 eop[4]; + u32 drops; +}; + +struct wtp_data { + /*TX path, Request Work request sub-path:*/ + + struct wtp_type_1 sge_pcie_cmd_req; /*SGE_DEBUG PC_Req_xOPn*/ + struct wtp_type_1 pcie_core_cmd_req; /*PCIE_CMDR_REQ_CNT*/ + + + /*TX path, Work request to uP sub-path*/ + struct wtp_type_1 core_pcie_cmd_rsp; /*PCIE_CMDR_RSP_CNT*/ + struct wtp_type_1 pcie_sge_cmd_rsp; /*SGE_DEBUG PC_Rsp_xOPn*/ + struct wtp_type_1 sge_cim; /*SGE_DEBUG CIM_xOPn*/ + + /*TX path, Data request path from ULP_TX to core*/ + struct wtp_type_2 utx_sge_dma_req; /*SGE UD_Rx_xOPn*/ + struct wtp_type_2 sge_pcie_dma_req; /*SGE PD_Req_Rdn (no eops)*/ + struct wtp_type_2 pcie_core_dma_req; /*PCIE_DMAR_REQ_CNT (no eops)*/ + + /*Main TX path, from core to wire*/ + struct wtp_type_2 core_pcie_dma_rsp; /*PCIE_DMAR_RSP_SOP_CNT/ + PCIE_DMAR_EOP_CNT*/ + struct wtp_type_2 pcie_sge_dma_rsp; /*SGE_DEBUG PD_Rsp_xOPn*/ + struct wtp_type_2 sge_utx; /*SGE_DEBUG U_Tx_xOPn*/ + struct wtp_type_2 utx_tp; /*ULP_TX_SE_CNT_CHn[xOP_CNT_ULP2TP]*/ + struct wtp_type_2 utx_tpcside; /*TP_DBG_CSIDE_RXn[RxXoPCnt]*/ + + struct wtp_type_2 tpcside_rxpld; + struct wtp_type_2 tpcside_rxarb; /*TP_DBG_CSIDE_RXn[RxArbXopCnt]*/ + struct wtp_type_2 tpcside_rxcpl; + + struct wtp_type_2 tpeside_mps; /*TP_DBG_ESDIE_PKT0[TxXoPCnt]*/ + struct wtp_type_2 tpeside_pm; + struct wtp_type_2 tpeside_pld; + + /*Tx path, PCIE t5 DMA stat*/ + struct wtp_type_2 pcie_t5_dma_stat3; + + /*Tx path, SGE debug data high index 6*/ + struct wtp_type_2 sge_debug_data_high_index_6; + + /*Tx path, SGE debug data high index 3*/ + struct wtp_type_2 sge_debug_data_high_index_3; + + /*Tx path, ULP SE CNT CHx*/ + struct wtp_type_2 ulp_se_cnt_chx; + + /*pcie cmd stat 2*/ + struct wtp_type_2 pcie_cmd_stat2; + + /*pcie cmd stat 3*/ + struct wtp_type_2 pcie_cmd_stat3; + + struct wtp_type_2 pcie_dma1_stat2_core; + + struct wtp_type_1 sge_work_req_pkt; + + struct wtp_type_2 sge_debug_data_high_indx5; + + /*Tx path, mac portx pkt count*/ + struct wtp_type_2 mac_portx_pkt_count; + + /*Rx path, mac porrx pkt count*/ + struct wtp_type_2 mac_porrx_pkt_count; + + /*Rx path, PCIE T5 dma1 stat 2*/ + struct wtp_type_2 pcie_dma1_stat2; + + /*Rx path, sge debug data high index 7*/ + struct wtp_type_2 sge_debug_data_high_indx7; + + /*Rx path, sge debug data high index 1*/ + struct wtp_type_1 sge_debug_data_high_indx1; + + /*Rx path, TP debug CSIDE Tx register*/ + struct wtp_type_1 utx_tpcside_tx; + + /*Rx path, LE DB response count*/ + struct wtp_type_0 le_db_rsp_cnt; + + /*Rx path, TP debug Eside PKTx*/ + struct wtp_type_2 tp_dbg_eside_pktx; + + /*Rx path, sge debug data high index 9*/ + struct wtp_type_1 sge_debug_data_high_indx9; + + /*Tx path, mac portx aFramesTransmittesok*/ + struct wtp_type_2 mac_portx_aframestra_ok; + + /*Rx path, mac portx aFramesTransmittesok*/ + struct wtp_type_2 mac_porrx_aframestra_ok; + + /*Tx path, MAC_PORT_MTIP_1G10G_RX_etherStatsPkts*/ + struct wtp_type_1 mac_portx_etherstatspkts; + + /*Rx path, MAC_PORT_MTIP_1G10G_RX_etherStatsPkts*/ + struct wtp_type_1 mac_porrx_etherstatspkts; + + struct wtp_type_3 tp_mps; /*MPS_TX_SE_CNT_TP01 and + MPS_TX_SE_CNT_TP34*/ + struct wtp_type_3 mps_xgm; /*MPS_TX_SE_CNT_MAC01 and + MPS_TX_SE_CNT_MAC34*/ + struct wtp_type_2 tx_xgm_xgm; /*XGMAC_PORT_PKT_CNT_PORT_n*/ + struct wtp_type_2 xgm_wire; /*XGMAC_PORT_XGM_STAT_TX_FRAME_LOW_PORT_N + (clear on read)*/ + + /*RX path, from wire to core.*/ + struct wtp_type_2 wire_xgm; /*XGMAC_PORT_XGM_STAT_RX_FRAMES_LOW_PORT_N + (clear on read)*/ + struct wtp_type_2 rx_xgm_xgm; /*XGMAC_PORT_PKT_CNT_PORT_n*/ + struct _xgm_mps { /*MPS_RX_SE_CNT_INn*/ + u32 sop[8]; /* => undef,*/ + u32 eop[8]; /* => undef,*/ + u32 drop; /* => undef,*/ + u32 cls_drop; /* => undef,*/ + u32 err; /* => undef,*/ + u32 bp; /* => undef,*/ + } xgm_mps; + + struct wtp_type_3 mps_tp; /*MPS_RX_SE_CNT_OUT01 and + MPS_RX_SE_CNT_OUT23*/ + struct wtp_type_2 mps_tpeside; /*TP_DBG_ESIDE_PKTn*/ + struct wtp_type_1 tpeside_pmrx; /*???*/ + struct wtp_type_2 pmrx_ulprx; /*ULP_RX_SE_CNT_CHn[xOP_CNT_INn]*/ + struct wtp_type_2 ulprx_tpcside; /*ULP_RX_SE_CNT_CHn[xOP_CNT_OUTn]*/ + struct wtp_type_2 tpcside_csw; /*TP_DBG_CSIDE_TXn[TxSopCnt]*/ + struct wtp_type_2 tpcside_pm; + struct wtp_type_2 tpcside_uturn; + struct wtp_type_2 tpcside_txcpl; + struct wtp_type_1 tp_csw; /*SGE_DEBUG CPLSW_TP_Rx_xOPn*/ + struct wtp_type_1 csw_sge; /*SGE_DEBUG T_Rx_xOPn*/ + struct wtp_type_2 sge_pcie; /*SGE_DEBUG PD_Req_SopN - + PD_Req_RdN - PD_ReqIntN*/ + struct wtp_type_2 sge_pcie_ints; /*SGE_DEBUG PD_Req_IntN*/ + struct wtp_type_2 pcie_core_dmaw; /*PCIE_DMAW_SOP_CNT and + PCIE_DMAW_EOP_CNT*/ + struct wtp_type_2 pcie_core_dmai; /*PCIE_DMAI_CNT*/ + +}; + +struct tp_mib_data { + struct tp_mib_type TP_MIB_MAC_IN_ERR_0; + struct tp_mib_type TP_MIB_MAC_IN_ERR_1; + struct tp_mib_type TP_MIB_MAC_IN_ERR_2; + struct tp_mib_type TP_MIB_MAC_IN_ERR_3; + struct tp_mib_type TP_MIB_HDR_IN_ERR_0; + struct tp_mib_type TP_MIB_HDR_IN_ERR_1; + struct tp_mib_type TP_MIB_HDR_IN_ERR_2; + struct tp_mib_type TP_MIB_HDR_IN_ERR_3; + struct tp_mib_type TP_MIB_TCP_IN_ERR_0; + struct tp_mib_type TP_MIB_TCP_IN_ERR_1; + struct tp_mib_type TP_MIB_TCP_IN_ERR_2; + struct tp_mib_type TP_MIB_TCP_IN_ERR_3; + struct tp_mib_type TP_MIB_TCP_OUT_RST; + struct tp_mib_type TP_MIB_TCP_IN_SEG_HI; + struct tp_mib_type TP_MIB_TCP_IN_SEG_LO; + struct tp_mib_type TP_MIB_TCP_OUT_SEG_HI; + struct tp_mib_type TP_MIB_TCP_OUT_SEG_LO; + struct tp_mib_type TP_MIB_TCP_RXT_SEG_HI; + struct tp_mib_type TP_MIB_TCP_RXT_SEG_LO; + struct tp_mib_type TP_MIB_TNL_CNG_DROP_0; + struct tp_mib_type TP_MIB_TNL_CNG_DROP_1; + struct tp_mib_type TP_MIB_TNL_CNG_DROP_2; + struct tp_mib_type TP_MIB_TNL_CNG_DROP_3; + struct tp_mib_type TP_MIB_OFD_CHN_DROP_0; + struct tp_mib_type TP_MIB_OFD_CHN_DROP_1; + struct tp_mib_type TP_MIB_OFD_CHN_DROP_2; + struct tp_mib_type TP_MIB_OFD_CHN_DROP_3; + struct tp_mib_type TP_MIB_TNL_OUT_PKT_0; + struct tp_mib_type TP_MIB_TNL_OUT_PKT_1; + struct tp_mib_type TP_MIB_TNL_OUT_PKT_2; + struct tp_mib_type TP_MIB_TNL_OUT_PKT_3; + struct tp_mib_type TP_MIB_TNL_IN_PKT_0; + struct tp_mib_type TP_MIB_TNL_IN_PKT_1; + struct tp_mib_type TP_MIB_TNL_IN_PKT_2; + struct tp_mib_type TP_MIB_TNL_IN_PKT_3; + struct tp_mib_type TP_MIB_TCP_V6IN_ERR_0; + struct tp_mib_type TP_MIB_TCP_V6IN_ERR_1; + struct tp_mib_type TP_MIB_TCP_V6IN_ERR_2; + struct tp_mib_type TP_MIB_TCP_V6IN_ERR_3; + struct tp_mib_type TP_MIB_TCP_V6OUT_RST; + struct tp_mib_type TP_MIB_TCP_V6IN_SEG_HI; + struct tp_mib_type TP_MIB_TCP_V6IN_SEG_LO; + struct tp_mib_type TP_MIB_TCP_V6OUT_SEG_HI; + struct tp_mib_type TP_MIB_TCP_V6OUT_SEG_LO; + struct tp_mib_type TP_MIB_TCP_V6RXT_SEG_HI; + struct tp_mib_type TP_MIB_TCP_V6RXT_SEG_LO; + struct tp_mib_type TP_MIB_OFD_ARP_DROP; + struct tp_mib_type TP_MIB_OFD_DFR_DROP; + struct tp_mib_type TP_MIB_CPL_IN_REQ_0; + struct tp_mib_type TP_MIB_CPL_IN_REQ_1; + struct tp_mib_type TP_MIB_CPL_IN_REQ_2; + struct tp_mib_type TP_MIB_CPL_IN_REQ_3; + struct tp_mib_type TP_MIB_CPL_OUT_RSP_0; + struct tp_mib_type TP_MIB_CPL_OUT_RSP_1; + struct tp_mib_type TP_MIB_CPL_OUT_RSP_2; + struct tp_mib_type TP_MIB_CPL_OUT_RSP_3; + struct tp_mib_type TP_MIB_TNL_LPBK_0; + struct tp_mib_type TP_MIB_TNL_LPBK_1; + struct tp_mib_type TP_MIB_TNL_LPBK_2; + struct tp_mib_type TP_MIB_TNL_LPBK_3; + struct tp_mib_type TP_MIB_TNL_DROP_0; + struct tp_mib_type TP_MIB_TNL_DROP_1; + struct tp_mib_type TP_MIB_TNL_DROP_2; + struct tp_mib_type TP_MIB_TNL_DROP_3; + struct tp_mib_type TP_MIB_FCOE_DDP_0; + struct tp_mib_type TP_MIB_FCOE_DDP_1; + struct tp_mib_type TP_MIB_FCOE_DDP_2; + struct tp_mib_type TP_MIB_FCOE_DDP_3; + struct tp_mib_type TP_MIB_FCOE_DROP_0; + struct tp_mib_type TP_MIB_FCOE_DROP_1; + struct tp_mib_type TP_MIB_FCOE_DROP_2; + struct tp_mib_type TP_MIB_FCOE_DROP_3; + struct tp_mib_type TP_MIB_FCOE_BYTE_0_HI; + struct tp_mib_type TP_MIB_FCOE_BYTE_0_LO; + struct tp_mib_type TP_MIB_FCOE_BYTE_1_HI; + struct tp_mib_type TP_MIB_FCOE_BYTE_1_LO; + struct tp_mib_type TP_MIB_FCOE_BYTE_2_HI; + struct tp_mib_type TP_MIB_FCOE_BYTE_2_LO; + struct tp_mib_type TP_MIB_FCOE_BYTE_3_HI; + struct tp_mib_type TP_MIB_FCOE_BYTE_3_LO; + struct tp_mib_type TP_MIB_OFD_VLN_DROP_0; + struct tp_mib_type TP_MIB_OFD_VLN_DROP_1; + struct tp_mib_type TP_MIB_OFD_VLN_DROP_2; + struct tp_mib_type TP_MIB_OFD_VLN_DROP_3; + struct tp_mib_type TP_MIB_USM_PKTS; + struct tp_mib_type TP_MIB_USM_DROP; + struct tp_mib_type TP_MIB_USM_BYTES_HI; + struct tp_mib_type TP_MIB_USM_BYTES_LO; + struct tp_mib_type TP_MIB_TID_DEL; + struct tp_mib_type TP_MIB_TID_INV; + struct tp_mib_type TP_MIB_TID_ACT; + struct tp_mib_type TP_MIB_TID_PAS; + struct tp_mib_type TP_MIB_RQE_DFR_MOD; + struct tp_mib_type TP_MIB_RQE_DFR_PKT; +}; + +struct cudbg_reg_info { + const char *name; + unsigned int addr; + unsigned int len; +}; + +struct tp1_reg_info { + char addr[10]; + char name[40]; +}; + +struct ireg_field { + u32 ireg_addr; + u32 ireg_data; + u32 ireg_local_offset; + u32 ireg_offset_range; +}; + +struct ireg_buf { + struct ireg_field tp_pio; + u32 outbuf[32]; +}; + +struct tx_rate { + u64 nrate[NCHAN]; + u64 orate[NCHAN]; + u32 nchan; +}; + +struct tid_info_region { + u32 ntids; + u32 nstids; + u32 stid_base; + u32 hash_base; + + u32 natids; + u32 nftids; + u32 ftid_base; + u32 aftid_base; + u32 aftid_end; + + /* Server filter region */ + u32 sftid_base; + u32 nsftids; + + /* UO context range */ + u32 uotid_base; + u32 nuotids; + + u32 sb; + u32 flags; + u32 le_db_conf; + u32 IP_users; + u32 IPv6_users; + + u32 hpftid_base; + u32 nhpftids; +}; + +struct tid_info_region_rev1 { + struct cudbg_ver_hdr ver_hdr; + struct tid_info_region tid; + u32 tid_start; + u32 reserved[16]; +}; + +struct struct_vpd_data { + u8 sn[SN_MAX_LEN + 1]; + u8 bn[BN_MAX_LEN + 1]; + u8 na[NA_MAX_LEN + 1]; + u8 mn[MN_MAX_LEN + 1]; + u16 fw_major; + u16 fw_minor; + u16 fw_micro; + u16 fw_build; + u32 scfg_vers; + u32 vpd_vers; +}; + +struct sw_state { + u32 fw_state; + u8 caller_string[100]; + u8 os_type; + u8 reserved[3]; + u32 reserved1[16]; +}; + +static u32 ATTRIBUTE_UNUSED t6_tp_pio_array[][4] = { + {0x7e40, 0x7e44, 0x020, 28}, /* t6_tp_pio_regs_20_to_3b */ + {0x7e40, 0x7e44, 0x040, 10}, /* t6_tp_pio_regs_40_to_49 */ + {0x7e40, 0x7e44, 0x050, 10}, /* t6_tp_pio_regs_50_to_59 */ + {0x7e40, 0x7e44, 0x060, 14}, /* t6_tp_pio_regs_60_to_6d */ + {0x7e40, 0x7e44, 0x06F, 1}, /* t6_tp_pio_regs_6f */ + {0x7e40, 0x7e44, 0x070, 6}, /* t6_tp_pio_regs_70_to_75 */ + {0x7e40, 0x7e44, 0x130, 18}, /* t6_tp_pio_regs_130_to_141 */ + {0x7e40, 0x7e44, 0x145, 19}, /* t6_tp_pio_regs_145_to_157 */ + {0x7e40, 0x7e44, 0x160, 1}, /* t6_tp_pio_regs_160 */ + {0x7e40, 0x7e44, 0x230, 25}, /* t6_tp_pio_regs_230_to_248 */ + {0x7e40, 0x7e44, 0x24a, 3}, /* t6_tp_pio_regs_24c */ + {0x7e40, 0x7e44, 0x8C0, 1} /* t6_tp_pio_regs_8c0 */ +}; + +static u32 ATTRIBUTE_UNUSED t5_tp_pio_array[][4] = { + {0x7e40, 0x7e44, 0x020, 28}, /* t5_tp_pio_regs_20_to_3b */ + {0x7e40, 0x7e44, 0x040, 19}, /* t5_tp_pio_regs_40_to_52 */ + {0x7e40, 0x7e44, 0x054, 2}, /* t5_tp_pio_regs_54_to_55 */ + {0x7e40, 0x7e44, 0x060, 13}, /* t5_tp_pio_regs_60_to_6c */ + {0x7e40, 0x7e44, 0x06F, 1}, /* t5_tp_pio_regs_6f */ + {0x7e40, 0x7e44, 0x120, 4}, /* t5_tp_pio_regs_120_to_123 */ + {0x7e40, 0x7e44, 0x12b, 2}, /* t5_tp_pio_regs_12b_to_12c */ + {0x7e40, 0x7e44, 0x12f, 21}, /* t5_tp_pio_regs_12f_to_143 */ + {0x7e40, 0x7e44, 0x145, 19}, /* t5_tp_pio_regs_145_to_157 */ + {0x7e40, 0x7e44, 0x230, 25}, /* t5_tp_pio_regs_230_to_248 */ + {0x7e40, 0x7e44, 0x8C0, 1} /* t5_tp_pio_regs_8c0 */ +}; + +static u32 ATTRIBUTE_UNUSED t6_ma_ireg_array[][4] = { + {0x78f8, 0x78fc, 0xa000, 23}, /* t6_ma_regs_a000_to_a016 */ + {0x78f8, 0x78fc, 0xa400, 30}, /* t6_ma_regs_a400_to_a41e */ + {0x78f8, 0x78fc, 0xa800, 20} /* t6_ma_regs_a800_to_a813 */ +}; + +static u32 ATTRIBUTE_UNUSED t6_ma_ireg_array2[][4] = { + {0x78f8, 0x78fc, 0xe400, 17}, /* t6_ma_regs_e400_to_e600 */ + {0x78f8, 0x78fc, 0xe640, 13} /* t6_ma_regs_e640_to_e7c0 */ +}; + +static u32 ATTRIBUTE_UNUSED t6_hma_ireg_array[][4] = { + {0x51320, 0x51324, 0xa000, 32} /* t6_hma_regs_a000_to_a01f */ +}; +static u32 ATTRIBUTE_UNUSED t5_pcie_pdbg_array[][4] = { + {0x5a04, 0x5a0c, 0x00, 0x20}, /* t5_pcie_pdbg_regs_00_to_20 */ + {0x5a04, 0x5a0c, 0x21, 0x20}, /* t5_pcie_pdbg_regs_21_to_40 */ + {0x5a04, 0x5a0c, 0x41, 0x10}, /* t5_pcie_pdbg_regs_41_to_50 */ +}; + +static u32 ATTRIBUTE_UNUSED t5_pcie_config_array[][2] = { + {0x0, 0x34}, + {0x3c, 0x40}, + {0x50, 0x64}, + {0x70, 0x80}, + {0x94, 0xa0}, + {0xb0, 0xb8}, + {0xd0, 0xd4}, + {0x100, 0x128}, + {0x140, 0x148}, + {0x150, 0x164}, + {0x170, 0x178}, + {0x180, 0x194}, + {0x1a0, 0x1b8}, + {0x1c0, 0x208}, +}; + +static u32 ATTRIBUTE_UNUSED t5_pcie_cdbg_array[][4] = { + {0x5a10, 0x5a18, 0x00, 0x20}, /* t5_pcie_cdbg_regs_00_to_20 */ + {0x5a10, 0x5a18, 0x21, 0x18}, /* t5_pcie_cdbg_regs_21_to_37 */ +}; + +static u32 ATTRIBUTE_UNUSED t6_tp_tm_pio_array[1][4] = { + {0x7e18, 0x7e1c, 0x0, 12} +}; + +static u32 ATTRIBUTE_UNUSED t5_tp_tm_pio_array[1][4] = { + {0x7e18, 0x7e1c, 0x0, 12} +}; + +static u32 ATTRIBUTE_UNUSED t5_pm_rx_array[][4] = { + {0x8FD0, 0x8FD4, 0x10000, 0x20}, /* t5_pm_rx_regs_10000_to_10020 */ + {0x8FD0, 0x8FD4, 0x10021, 0x0D}, /* t5_pm_rx_regs_10021_to_1002c */ +}; + +static u32 ATTRIBUTE_UNUSED t5_pm_tx_array[][4] = { + {0x8FF0, 0x8FF4, 0x10000, 0x20}, /* t5_pm_tx_regs_10000_to_10020 */ + {0x8FF0, 0x8FF4, 0x10021, 0x1D}, /* t5_pm_tx_regs_10021_to_1003c */ +}; + +static u32 ATTRIBUTE_UNUSED t6_tp_mib_index_array[6][4] = { + {0x7e50, 0x7e54, 0x0, 13}, + {0x7e50, 0x7e54, 0x10, 6}, + {0x7e50, 0x7e54, 0x18, 21}, + {0x7e50, 0x7e54, 0x30, 32}, + {0x7e50, 0x7e54, 0x50, 22}, + {0x7e50, 0x7e54, 0x68, 12} +}; + +static u32 ATTRIBUTE_UNUSED t5_tp_mib_index_array[9][4] = { + {0x7e50, 0x7e54, 0x0, 13}, + {0x7e50, 0x7e54, 0x10, 6}, + {0x7e50, 0x7e54, 0x18, 8}, + {0x7e50, 0x7e54, 0x20, 13}, + {0x7e50, 0x7e54, 0x30, 16}, + {0x7e50, 0x7e54, 0x40, 16}, + {0x7e50, 0x7e54, 0x50, 16}, + {0x7e50, 0x7e54, 0x60, 6}, + {0x7e50, 0x7e54, 0x68, 4} +}; + +static u32 ATTRIBUTE_UNUSED t5_sge_dbg_index_array[9][4] = { + {0x10cc, 0x10d0, 0x0, 16}, + {0x10cc, 0x10d4, 0x0, 16}, +}; + +static u32 ATTRIBUTE_UNUSED t6_up_cim_reg_array[][4] = { + {0x7b50, 0x7b54, 0x2000, 0x20}, /* up_cim_2000_to_207c */ + {0x7b50, 0x7b54, 0x2080, 0x1d}, /* up_cim_2080_to_20fc */ + {0x7b50, 0x7b54, 0x00, 0x20}, /* up_cim_00_to_7c */ + {0x7b50, 0x7b54, 0x80, 0x20}, /* up_cim_80_to_fc */ + {0x7b50, 0x7b54, 0x100, 0x11}, /* up_cim_100_to_14c */ + {0x7b50, 0x7b54, 0x200, 0x10}, /* up_cim_200_to_23c */ + {0x7b50, 0x7b54, 0x240, 0x2}, /* up_cim_240_to_244 */ + {0x7b50, 0x7b54, 0x250, 0x2}, /* up_cim_250_to_254 */ + {0x7b50, 0x7b54, 0x260, 0x2}, /* up_cim_260_to_264 */ + {0x7b50, 0x7b54, 0x270, 0x2}, /* up_cim_270_to_274 */ + {0x7b50, 0x7b54, 0x280, 0x20}, /* up_cim_280_to_2fc */ + {0x7b50, 0x7b54, 0x300, 0x20}, /* up_cim_300_to_37c */ + {0x7b50, 0x7b54, 0x380, 0x14}, /* up_cim_380_to_3cc */ + +}; + +static u32 ATTRIBUTE_UNUSED t5_up_cim_reg_array[][4] = { + {0x7b50, 0x7b54, 0x2000, 0x20}, /* up_cim_2000_to_207c */ + {0x7b50, 0x7b54, 0x2080, 0x19}, /* up_cim_2080_to_20ec */ + {0x7b50, 0x7b54, 0x00, 0x20}, /* up_cim_00_to_7c */ + {0x7b50, 0x7b54, 0x80, 0x20}, /* up_cim_80_to_fc */ + {0x7b50, 0x7b54, 0x100, 0x11}, /* up_cim_100_to_14c */ + {0x7b50, 0x7b54, 0x200, 0x10}, /* up_cim_200_to_23c */ + {0x7b50, 0x7b54, 0x240, 0x2}, /* up_cim_240_to_244 */ + {0x7b50, 0x7b54, 0x250, 0x2}, /* up_cim_250_to_254 */ + {0x7b50, 0x7b54, 0x260, 0x2}, /* up_cim_260_to_264 */ + {0x7b50, 0x7b54, 0x270, 0x2}, /* up_cim_270_to_274 */ + {0x7b50, 0x7b54, 0x280, 0x20}, /* up_cim_280_to_2fc */ + {0x7b50, 0x7b54, 0x300, 0x20}, /* up_cim_300_to_37c */ + {0x7b50, 0x7b54, 0x380, 0x14}, /* up_cim_380_to_3cc */ +}; + +#endif Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_entity.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_flash_utils.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_flash_utils.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_flash_utils.c (revision 322022) @@ -0,0 +1,492 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "common/common.h" +#include "common/t4_regs.h" +#include "cudbg.h" +#include "cudbg_lib_common.h" + +enum { + SF_ATTEMPTS = 10, /* max retries for SF operations */ + + /* flash command opcodes */ + SF_PROG_PAGE = 2, /* program page */ + SF_WR_DISABLE = 4, /* disable writes */ + SF_RD_STATUS = 5, /* read status register */ + SF_WR_ENABLE = 6, /* enable writes */ + SF_RD_DATA_FAST = 0xb, /* read flash */ + SF_RD_ID = 0x9f, /* read ID */ + SF_ERASE_SECTOR = 0xd8, /* erase sector */ +}; + +int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size); +int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size, + u32 start_address); + +void +update_skip_size(struct cudbg_flash_sec_info *sec_info, u32 size) +{ + sec_info->skip_size += size; +} + +static +void set_sector_availability(struct cudbg_flash_sec_info *sec_info, + int sector_nu, int avail) +{ + sector_nu -= CUDBG_START_SEC; + if (avail) + set_dbg_bitmap(sec_info->sec_bitmap, sector_nu); + else + reset_dbg_bitmap(sec_info->sec_bitmap, sector_nu); +} + +/* This function will return empty sector available for filling */ +static int +find_empty_sec(struct cudbg_flash_sec_info *sec_info) +{ + int i, index, bit; + + for (i = CUDBG_START_SEC; i < CUDBG_SF_MAX_SECTOR; i++) { + index = (i - CUDBG_START_SEC) / 8; + bit = (i - CUDBG_START_SEC) % 8; + if (!(sec_info->sec_bitmap[index] & (1 << bit))) + return i; + } + + return CUDBG_STATUS_FLASH_FULL; +} + +/* This function will get header initially. If header is already there + * then it will update that header */ +static void update_headers(void *handle, struct cudbg_buffer *dbg_buff, + u64 timestamp, u32 cur_entity_hdr_offset, + u32 start_offset, u32 ext_size) +{ + struct cudbg_private *priv = handle; + struct cudbg_flash_sec_info *sec_info = &priv->sec_info; + void *sec_hdr; + struct cudbg_hdr *cudbg_hdr; + struct cudbg_flash_hdr *flash_hdr; + struct cudbg_entity_hdr *entity_hdr; + u32 hdr_offset; + u32 data_hdr_size; + u32 total_hdr_size; + u32 sec_hdr_start_addr; + + data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) + + sizeof(struct cudbg_hdr); + total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr); + sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size; + sec_hdr = sec_info->sec_data + sec_hdr_start_addr; + + flash_hdr = (struct cudbg_flash_hdr *)(sec_hdr); + cudbg_hdr = (struct cudbg_hdr *)dbg_buff->data; + + /* initially initialize flash hdr and copy all data headers and + * in next calling (else part) copy only current entity header + */ + if ((start_offset - sec_info->skip_size) == data_hdr_size) { + flash_hdr->signature = CUDBG_FL_SIGNATURE; + flash_hdr->major_ver = CUDBG_FL_MAJOR_VERSION; + flash_hdr->minor_ver = CUDBG_FL_MINOR_VERSION; + flash_hdr->build_ver = CUDBG_FL_BUILD_VERSION; + flash_hdr->hdr_len = sizeof(struct cudbg_flash_hdr); + hdr_offset = sizeof(struct cudbg_flash_hdr); + + memcpy((void *)((char *)sec_hdr + hdr_offset), + (void *)((char *)dbg_buff->data), data_hdr_size); + } else + memcpy((void *)((char *)sec_hdr + + sizeof(struct cudbg_flash_hdr) + + cur_entity_hdr_offset), + (void *)((char *)dbg_buff->data + + cur_entity_hdr_offset), + sizeof(struct cudbg_entity_hdr)); + + hdr_offset = data_hdr_size + sizeof(struct cudbg_flash_hdr); + flash_hdr->data_len = cudbg_hdr->data_len - sec_info->skip_size; + flash_hdr->timestamp = timestamp; + + entity_hdr = (struct cudbg_entity_hdr *)((char *)sec_hdr + + sizeof(struct cudbg_flash_hdr) + + cur_entity_hdr_offset); + /* big entity like mc need to be skipped */ + entity_hdr->start_offset -= sec_info->skip_size; + + cudbg_hdr = (struct cudbg_hdr *)((char *)sec_hdr + + sizeof(struct cudbg_flash_hdr)); + cudbg_hdr->data_len = flash_hdr->data_len; + flash_hdr->data_len += ext_size; +} + +/* Write CUDBG data into serial flash */ +int cudbg_write_flash(void *handle, u64 timestamp, void *data, + u32 start_offset, u32 cur_entity_hdr_offset, + u32 cur_entity_size, + u32 ext_size) +{ + struct cudbg_private *priv = handle; + struct cudbg_init *cudbg_init = &priv->dbg_init; + struct cudbg_flash_sec_info *sec_info = &priv->sec_info; + struct adapter *adap = cudbg_init->adap; + struct cudbg_flash_hdr *flash_hdr = NULL; + struct cudbg_buffer *dbg_buff = (struct cudbg_buffer *)data; + u32 data_hdr_size; + u32 total_hdr_size; + u32 tmp_size; + u32 sec_data_offset; + u32 sec_hdr_start_addr; + u32 sec_data_size; + u32 space_left; + int rc = 0; + int sec; + + data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) + + sizeof(struct cudbg_hdr); + total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr); + sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size; + sec_data_size = sec_hdr_start_addr; + + cudbg_init->print("\tWriting %u bytes to flash\n", cur_entity_size); + + /* this function will get header if sec_info->sec_data does not + * have any header and + * will update the header if it has header + */ + update_headers(handle, dbg_buff, timestamp, + cur_entity_hdr_offset, + start_offset, ext_size); + + if (ext_size) { + cur_entity_size += sizeof(struct cudbg_entity_hdr); + start_offset = dbg_buff->offset - cur_entity_size; + } + + flash_hdr = (struct cudbg_flash_hdr *)(sec_info->sec_data + + sec_hdr_start_addr); + + if (flash_hdr->data_len > CUDBG_FLASH_SIZE) { + rc = CUDBG_STATUS_FLASH_FULL; + goto out; + } + + space_left = CUDBG_FLASH_SIZE - flash_hdr->data_len; + + if (cur_entity_size > space_left) { + rc = CUDBG_STATUS_FLASH_FULL; + goto out; + } + + while (cur_entity_size > 0) { + sec = find_empty_sec(sec_info); + if (sec_info->par_sec) { + sec_data_offset = sec_info->par_sec_offset; + set_sector_availability(sec_info, sec_info->par_sec, 0); + sec_info->par_sec = 0; + sec_info->par_sec_offset = 0; + + } else { + sec_info->cur_seq_no++; + flash_hdr->sec_seq_no = sec_info->cur_seq_no; + sec_data_offset = 0; + } + + if (cur_entity_size + sec_data_offset > sec_data_size) { + tmp_size = sec_data_size - sec_data_offset; + } else { + tmp_size = cur_entity_size; + sec_info->par_sec = sec; + sec_info->par_sec_offset = cur_entity_size + + sec_data_offset; + } + + memcpy((void *)((char *)sec_info->sec_data + sec_data_offset), + (void *)((char *)dbg_buff->data + start_offset), + tmp_size); + + rc = write_flash(adap, sec, sec_info->sec_data, + CUDBG_SF_SECTOR_SIZE); + if (rc) + goto out; + + cur_entity_size -= tmp_size; + set_sector_availability(sec_info, sec, 1); + start_offset += tmp_size; + } +out: + return rc; +} + +int write_flash(struct adapter *adap, u32 start_sec, void *data, u32 size) +{ + unsigned int addr; + unsigned int i, n; + unsigned int sf_sec_size; + int rc = 0; + + u8 *ptr = (u8 *)data; + + sf_sec_size = adap->params.sf_size/adap->params.sf_nsec; + + addr = start_sec * CUDBG_SF_SECTOR_SIZE; + i = DIV_ROUND_UP(size,/* # of sectors spanned */ + sf_sec_size); + + rc = t4_flash_erase_sectors(adap, start_sec, + start_sec + i - 1); + /* + * If size == 0 then we're simply erasing the FLASH sectors associated + * with the on-adapter OptionROM Configuration File. + */ + + if (rc || size == 0) + goto out; + + /* this will write to the flash up to SF_PAGE_SIZE at a time */ + for (i = 0; i < size; i += SF_PAGE_SIZE) { + if ((size - i) < SF_PAGE_SIZE) + n = size - i; + else + n = SF_PAGE_SIZE; + rc = t4_write_flash(adap, addr, n, ptr, 0); + if (rc) + goto out; + + addr += n; + ptr += n; + } + + return 0; +out: + return rc; +} + +int cudbg_read_flash_details(void *handle, struct cudbg_flash_hdr *data) +{ + int rc; + rc = cudbg_read_flash(handle, (void *)data, + sizeof(struct cudbg_flash_hdr), 0); + + return rc; +} + +int cudbg_read_flash_data(void *handle, void *buf, u32 buf_size) +{ + int rc; + u32 total_hdr_size, data_header_size; + void *payload = NULL; + u32 payload_size = 0; + + data_header_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) + + sizeof(struct cudbg_hdr); + total_hdr_size = data_header_size + sizeof(struct cudbg_flash_hdr); + + /* Copy flash header to buffer */ + rc = cudbg_read_flash(handle, buf, total_hdr_size, 0); + if (rc != 0) + goto out; + payload = (char *)buf + total_hdr_size; + payload_size = buf_size - total_hdr_size; + + /* Reading flash data to buf */ + rc = cudbg_read_flash(handle, payload, payload_size, 1); + if (rc != 0) + goto out; + +out: + return rc; +} + +int cudbg_read_flash(void *handle, void *data, u32 size, int data_flag) +{ + struct cudbg_private *priv = handle; + struct cudbg_init *cudbg_init = &priv->dbg_init; + struct cudbg_flash_sec_info *sec_info = &priv->sec_info; + struct adapter *adap = cudbg_init->adap; + struct cudbg_flash_hdr flash_hdr; + u32 total_hdr_size; + u32 data_hdr_size; + u32 sec_hdr_start_addr; + u32 tmp_size; + u32 data_offset = 0; + u32 i, j; + int rc; + + rc = t4_get_flash_params(adap); + if (rc) { + cudbg_init->print("\nGet flash params failed." + "Try Again...readflash\n\n"); + return rc; + } + + data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) + + sizeof(struct cudbg_hdr); + total_hdr_size = data_hdr_size + sizeof(struct cudbg_flash_hdr); + sec_hdr_start_addr = CUDBG_SF_SECTOR_SIZE - total_hdr_size; + + if (!data_flag) { + /* fill header */ + if (!sec_info->max_timestamp) { + /* finding max time stamp because it may + * have older filled sector also + */ + memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr)); + rc = read_flash(adap, CUDBG_START_SEC, &flash_hdr, + sizeof(struct cudbg_flash_hdr), + sec_hdr_start_addr); + + if (flash_hdr.signature == CUDBG_FL_SIGNATURE) { + sec_info->max_timestamp = flash_hdr.timestamp; + } else { + rc = read_flash(adap, CUDBG_START_SEC + 1, + &flash_hdr, + sizeof(struct cudbg_flash_hdr), + sec_hdr_start_addr); + + if (flash_hdr.signature == CUDBG_FL_SIGNATURE) + sec_info->max_timestamp = + flash_hdr.timestamp; + else { + cudbg_init->print("\n\tNo cudbg dump "\ + "found in flash\n\n"); + return CUDBG_STATUS_NO_SIGNATURE; + } + + } + + /* finding max sequence number because max sequenced + * sector has updated header + */ + for (i = CUDBG_START_SEC; i < + CUDBG_SF_MAX_SECTOR; i++) { + memset(&flash_hdr, 0, + sizeof(struct cudbg_flash_hdr)); + rc = read_flash(adap, i, &flash_hdr, + sizeof(struct cudbg_flash_hdr), + sec_hdr_start_addr); + + if (flash_hdr.signature == CUDBG_FL_SIGNATURE && + sec_info->max_timestamp == + flash_hdr.timestamp && + sec_info->max_seq_no <= + flash_hdr.sec_seq_no) { + if (sec_info->max_seq_no == + flash_hdr.sec_seq_no) { + if (sec_info->hdr_data_len < + flash_hdr.data_len) + sec_info->max_seq_sec = i; + } else { + sec_info->max_seq_sec = i; + sec_info->hdr_data_len = + flash_hdr.data_len; + } + sec_info->max_seq_no = flash_hdr.sec_seq_no; + } + } + } + rc = read_flash(adap, sec_info->max_seq_sec, + (struct cudbg_flash_hdr *)data, + size, sec_hdr_start_addr); + + if (rc) + cudbg_init->print("Read flash header failed, rc %d\n", + rc); + + return rc; + } + + /* finding sector sequence sorted */ + for (i = 1; i <= sec_info->max_seq_no; i++) { + for (j = CUDBG_START_SEC; j < CUDBG_SF_MAX_SECTOR; j++) { + memset(&flash_hdr, 0, sizeof(struct cudbg_flash_hdr)); + rc = read_flash(adap, j, &flash_hdr, + sizeof(struct cudbg_flash_hdr), + sec_hdr_start_addr); + + if (flash_hdr.signature == + CUDBG_FL_SIGNATURE && + sec_info->max_timestamp == + flash_hdr.timestamp && + flash_hdr.sec_seq_no == i) { + if (size + total_hdr_size > + CUDBG_SF_SECTOR_SIZE) + tmp_size = CUDBG_SF_SECTOR_SIZE - + total_hdr_size; + else + tmp_size = size; + + if ((i != sec_info->max_seq_no) || + (i == sec_info->max_seq_no && + j == sec_info->max_seq_sec)){ + /* filling data buffer with sector data + * except sector header + */ + rc = read_flash(adap, j, + (void *)((char *)data + + data_offset), + tmp_size, 0); + data_offset += (tmp_size); + size -= (tmp_size); + break; + } + } + } + } + + return rc; +} + +int read_flash(struct adapter *adap, u32 start_sec , void *data, u32 size, + u32 start_address) +{ + unsigned int addr, i, n; + int rc; + u32 *ptr = (u32 *)data; + addr = start_sec * CUDBG_SF_SECTOR_SIZE + start_address; + size = size / 4; + for (i = 0; i < size; i += SF_PAGE_SIZE) { + if ((size - i) < SF_PAGE_SIZE) + n = size - i; + else + n = SF_PAGE_SIZE; + rc = t4_read_flash(adap, addr, n, ptr, 0); + if (rc) + goto out; + + addr = addr + (n*4); + ptr += n; + } + + return 0; +out: + return rc; +} Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_flash_utils.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.c (revision 322022) @@ -0,0 +1,4433 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "common/common.h" +#include "common/t4_regs.h" +#include "cudbg.h" +#include "cudbg_lib_common.h" +#include "cudbg_lib.h" +#include "cudbg_entity.h" +#define BUFFER_WARN_LIMIT 10000000 + +struct large_entity large_entity_list[] = { + {CUDBG_EDC0, 0, 0}, + {CUDBG_EDC1, 0 , 0}, + {CUDBG_MC0, 0, 0}, + {CUDBG_MC1, 0, 0} +}; + +static int is_fw_attached(struct cudbg_init *pdbg_init) +{ + + return (pdbg_init->adap->flags & FW_OK); +} + +/* This function will add additional padding bytes into debug_buffer to make it + * 4 byte aligned.*/ +static void align_debug_buffer(struct cudbg_buffer *dbg_buff, + struct cudbg_entity_hdr *entity_hdr) +{ + u8 zero_buf[4] = {0}; + u8 padding, remain; + + remain = (dbg_buff->offset - entity_hdr->start_offset) % 4; + padding = 4 - remain; + if (remain) { + memcpy(((u8 *) dbg_buff->data) + dbg_buff->offset, &zero_buf, + padding); + dbg_buff->offset += padding; + entity_hdr->num_pad = padding; + } + + entity_hdr->size = dbg_buff->offset - entity_hdr->start_offset; +} + +static void read_sge_ctxt(struct cudbg_init *pdbg_init, u32 cid, + enum ctxt_type ctype, u32 *data) +{ + struct adapter *padap = pdbg_init->adap; + int rc = -1; + + if (is_fw_attached(pdbg_init)) + rc = t4_sge_ctxt_rd(padap, padap->mbox, cid, ctype, + data); + + if (rc) + t4_sge_ctxt_rd_bd(padap, cid, ctype, data); +} + +static int get_next_ext_entity_hdr(void *outbuf, u32 *ext_size, + struct cudbg_buffer *dbg_buff, + struct cudbg_entity_hdr **entity_hdr) +{ + struct cudbg_hdr *cudbg_hdr = (struct cudbg_hdr *)outbuf; + int rc = 0; + u32 ext_offset = cudbg_hdr->data_len; + *ext_size = 0; + + if (dbg_buff->size - dbg_buff->offset <= + sizeof(struct cudbg_entity_hdr)) { + rc = CUDBG_STATUS_BUFFER_SHORT; + goto err; + } + + *entity_hdr = (struct cudbg_entity_hdr *) + ((char *)outbuf + cudbg_hdr->data_len); + + /* Find the last extended entity header */ + while ((*entity_hdr)->size) { + + ext_offset += sizeof(struct cudbg_entity_hdr) + + (*entity_hdr)->size; + + *ext_size += (*entity_hdr)->size + + sizeof(struct cudbg_entity_hdr); + + if (dbg_buff->size - dbg_buff->offset + *ext_size <= + sizeof(struct cudbg_entity_hdr)) { + rc = CUDBG_STATUS_BUFFER_SHORT; + goto err; + } + + if (ext_offset != (*entity_hdr)->next_ext_offset) { + ext_offset -= sizeof(struct cudbg_entity_hdr) + + (*entity_hdr)->size; + break; + } + + (*entity_hdr)->next_ext_offset = *ext_size; + + *entity_hdr = (struct cudbg_entity_hdr *) + ((char *)outbuf + + ext_offset); + } + + /* update the data offset */ + dbg_buff->offset = ext_offset; +err: + return rc; +} + +static int wr_entity_to_flash(void *handle, struct cudbg_buffer *dbg_buff, + u32 cur_entity_data_offset, + u32 cur_entity_size, + int entity_nu, u32 ext_size) +{ + struct cudbg_private *priv = handle; + struct cudbg_init *cudbg_init = &priv->dbg_init; + struct cudbg_flash_sec_info *sec_info = &priv->sec_info; + u64 timestamp; + u32 cur_entity_hdr_offset = sizeof(struct cudbg_hdr); + u32 remain_flash_size; + u32 flash_data_offset; + u32 data_hdr_size; + int rc = -1; + + data_hdr_size = CUDBG_MAX_ENTITY * sizeof(struct cudbg_entity_hdr) + + sizeof(struct cudbg_hdr); + + flash_data_offset = (FLASH_CUDBG_NSECS * + (sizeof(struct cudbg_flash_hdr) + + data_hdr_size)) + + (cur_entity_data_offset - data_hdr_size); + + if (flash_data_offset > CUDBG_FLASH_SIZE) { + update_skip_size(sec_info, cur_entity_size); + if (cudbg_init->verbose) + cudbg_init->print("Large entity skipping...\n"); + return rc; + } + + remain_flash_size = CUDBG_FLASH_SIZE - flash_data_offset; + + if (cur_entity_size > remain_flash_size) { + update_skip_size(sec_info, cur_entity_size); + if (cudbg_init->verbose) + cudbg_init->print("Large entity skipping...\n"); + } else { + timestamp = 0; + + cur_entity_hdr_offset += + (sizeof(struct cudbg_entity_hdr) * + (entity_nu - 1)); + + rc = cudbg_write_flash(handle, timestamp, dbg_buff, + cur_entity_data_offset, + cur_entity_hdr_offset, + cur_entity_size, + ext_size); + if (rc == CUDBG_STATUS_FLASH_FULL && cudbg_init->verbose) + cudbg_init->print("\n\tFLASH is full... " + "can not write in flash more\n\n"); + } + + return rc; +} + +int cudbg_collect(void *handle, void *outbuf, u32 *outbuf_size) +{ + struct cudbg_entity_hdr *entity_hdr = NULL; + struct cudbg_entity_hdr *ext_entity_hdr = NULL; + struct cudbg_hdr *cudbg_hdr; + struct cudbg_buffer dbg_buff; + struct cudbg_error cudbg_err = {0}; + int large_entity_code; + + u8 *dbg_bitmap = ((struct cudbg_private *)handle)->dbg_init.dbg_bitmap; + struct cudbg_init *cudbg_init = + &(((struct cudbg_private *)handle)->dbg_init); + struct adapter *padap = cudbg_init->adap; + u32 total_size, remaining_buf_size; + u32 ext_size = 0; + int index, bit, i, rc = -1; + int all; + bool flag_ext = 0; + + reset_skip_entity(); + + dbg_buff.data = outbuf; + dbg_buff.size = *outbuf_size; + dbg_buff.offset = 0; + + cudbg_hdr = (struct cudbg_hdr *)dbg_buff.data; + cudbg_hdr->signature = CUDBG_SIGNATURE; + cudbg_hdr->hdr_len = sizeof(struct cudbg_hdr); + cudbg_hdr->major_ver = CUDBG_MAJOR_VERSION; + cudbg_hdr->minor_ver = CUDBG_MINOR_VERSION; + cudbg_hdr->max_entities = CUDBG_MAX_ENTITY; + cudbg_hdr->chip_ver = padap->params.chipid; + + if (cudbg_hdr->data_len) + flag_ext = 1; + + if (cudbg_init->use_flash) { +#ifndef notyet + rc = t4_get_flash_params(padap); + if (rc) { + if (cudbg_init->verbose) + cudbg_init->print("\nGet flash params failed.\n\n"); + cudbg_init->use_flash = 0; + } +#endif + +#ifdef notyet + /* Timestamp is mandatory. If it is not passed then disable + * flash support + */ + if (!cudbg_init->dbg_params[CUDBG_TIMESTAMP_PARAM].u.time) { + if (cudbg_init->verbose) + cudbg_init->print("\nTimestamp param missing," + "so ignoring flash write request\n\n"); + cudbg_init->use_flash = 0; + } +#endif + } + + if (sizeof(struct cudbg_entity_hdr) * CUDBG_MAX_ENTITY > + dbg_buff.size) { + rc = CUDBG_STATUS_SMALL_BUFF; + total_size = cudbg_hdr->hdr_len; + goto err; + } + + /* If ext flag is set then move the offset to the end of the buf + * so that we can add ext entities + */ + if (flag_ext) { + ext_entity_hdr = (struct cudbg_entity_hdr *) + ((char *)outbuf + cudbg_hdr->hdr_len + + (sizeof(struct cudbg_entity_hdr) * + (CUDBG_EXT_ENTITY - 1))); + ext_entity_hdr->start_offset = cudbg_hdr->data_len; + ext_entity_hdr->entity_type = CUDBG_EXT_ENTITY; + ext_entity_hdr->size = 0; + dbg_buff.offset = cudbg_hdr->data_len; + } else { + dbg_buff.offset += cudbg_hdr->hdr_len; /* move 24 bytes*/ + dbg_buff.offset += CUDBG_MAX_ENTITY * + sizeof(struct cudbg_entity_hdr); + } + + total_size = dbg_buff.offset; + all = dbg_bitmap[0] & (1 << CUDBG_ALL); + + /*sort(large_entity_list);*/ + + for (i = 1; i < CUDBG_MAX_ENTITY; i++) { + index = i / 8; + bit = i % 8; + + if (entity_list[i].bit == CUDBG_EXT_ENTITY) + continue; + + if (all || (dbg_bitmap[index] & (1 << bit))) { + + if (!flag_ext) { + rc = get_entity_hdr(outbuf, i, dbg_buff.size, + &entity_hdr); + if (rc) + cudbg_hdr->hdr_flags = rc; + } else { + rc = get_next_ext_entity_hdr(outbuf, &ext_size, + &dbg_buff, + &entity_hdr); + if (rc) + goto err; + + /* move the offset after the ext header */ + dbg_buff.offset += + sizeof(struct cudbg_entity_hdr); + } + + entity_hdr->entity_type = i; + entity_hdr->start_offset = dbg_buff.offset; + /* process each entity by calling process_entity fp */ + remaining_buf_size = dbg_buff.size - dbg_buff.offset; + + if ((remaining_buf_size <= BUFFER_WARN_LIMIT) && + is_large_entity(i)) { + if (cudbg_init->verbose) + cudbg_init->print("Skipping %s\n", + entity_list[i].name); + skip_entity(i); + continue; + } else { + + /* If fw_attach is 0, then skip entities which + * communicates with firmware + */ + + if (!is_fw_attached(cudbg_init) && + (entity_list[i].flag & + (1 << ENTITY_FLAG_FW_NO_ATTACH))) { + if (cudbg_init->verbose) + cudbg_init->print("Skipping %s entity,"\ + "because fw_attach "\ + "is 0\n", + entity_list[i].name); + continue; + } + + if (cudbg_init->verbose) + cudbg_init->print("collecting debug entity: "\ + "%s\n", entity_list[i].name); + memset(&cudbg_err, 0, + sizeof(struct cudbg_error)); + rc = process_entity[i-1](cudbg_init, &dbg_buff, + &cudbg_err); + } + + if (rc) { + entity_hdr->size = 0; + dbg_buff.offset = entity_hdr->start_offset; + } else + align_debug_buffer(&dbg_buff, entity_hdr); + + if (cudbg_err.sys_err) + rc = CUDBG_SYSTEM_ERROR; + + entity_hdr->hdr_flags = rc; + entity_hdr->sys_err = cudbg_err.sys_err; + entity_hdr->sys_warn = cudbg_err.sys_warn; + + /* We don't want to include ext entity size in global + * header + */ + if (!flag_ext) + total_size += entity_hdr->size; + + cudbg_hdr->data_len = total_size; + *outbuf_size = total_size; + + /* consider the size of the ext entity header and data + * also + */ + if (flag_ext) { + ext_size += (sizeof(struct cudbg_entity_hdr) + + entity_hdr->size); + entity_hdr->start_offset -= cudbg_hdr->data_len; + ext_entity_hdr->size = ext_size; + entity_hdr->next_ext_offset = ext_size; + entity_hdr->flag |= CUDBG_EXT_DATA_VALID; + } + + if (cudbg_init->use_flash) { + if (flag_ext) { + wr_entity_to_flash(handle, + &dbg_buff, + ext_entity_hdr-> + start_offset, + entity_hdr-> + size, + CUDBG_EXT_ENTITY, + ext_size); + } + else + wr_entity_to_flash(handle, + &dbg_buff, + entity_hdr->\ + start_offset, + entity_hdr->size, + i, ext_size); + } + } + } + + for (i = 0; i < sizeof(large_entity_list) / sizeof(struct large_entity); + i++) { + large_entity_code = large_entity_list[i].entity_code; + if (large_entity_list[i].skip_flag) { + if (!flag_ext) { + rc = get_entity_hdr(outbuf, large_entity_code, + dbg_buff.size, &entity_hdr); + if (rc) + cudbg_hdr->hdr_flags = rc; + } else { + rc = get_next_ext_entity_hdr(outbuf, &ext_size, + &dbg_buff, + &entity_hdr); + if (rc) + goto err; + + dbg_buff.offset += + sizeof(struct cudbg_entity_hdr); + } + + /* If fw_attach is 0, then skip entities which + * communicates with firmware + */ + if (!is_fw_attached(cudbg_init) && + (entity_list[large_entity_code].flag & + (1 << ENTITY_FLAG_FW_NO_ATTACH))) { + if (cudbg_init->verbose) + cudbg_init->print("Skipping %s entity,"\ + "because fw_attach "\ + "is 0\n", + entity_list[large_entity_code] + .name); + continue; + } + + entity_hdr->entity_type = large_entity_code; + entity_hdr->start_offset = dbg_buff.offset; + if (cudbg_init->verbose) + cudbg_init->print("Re-trying debug entity: %s\n", + entity_list[large_entity_code].name); + + memset(&cudbg_err, 0, sizeof(struct cudbg_error)); + rc = process_entity[large_entity_code - 1](cudbg_init, + &dbg_buff, + &cudbg_err); + if (rc) { + entity_hdr->size = 0; + dbg_buff.offset = entity_hdr->start_offset; + } else + align_debug_buffer(&dbg_buff, entity_hdr); + + if (cudbg_err.sys_err) + rc = CUDBG_SYSTEM_ERROR; + + entity_hdr->hdr_flags = rc; + entity_hdr->sys_err = cudbg_err.sys_err; + entity_hdr->sys_warn = cudbg_err.sys_warn; + + /* We don't want to include ext entity size in global + * header + */ + if (!flag_ext) + total_size += entity_hdr->size; + + cudbg_hdr->data_len = total_size; + *outbuf_size = total_size; + + /* consider the size of the ext entity header and + * data also + */ + if (flag_ext) { + ext_size += (sizeof(struct cudbg_entity_hdr) + + entity_hdr->size); + entity_hdr->start_offset -= + cudbg_hdr->data_len; + ext_entity_hdr->size = ext_size; + entity_hdr->flag |= CUDBG_EXT_DATA_VALID; + } + + if (cudbg_init->use_flash) { + if (flag_ext) + wr_entity_to_flash(handle, + &dbg_buff, + ext_entity_hdr-> + start_offset, + entity_hdr->size, + CUDBG_EXT_ENTITY, + ext_size); + else + wr_entity_to_flash(handle, + &dbg_buff, + entity_hdr-> + start_offset, + entity_hdr-> + size, + large_entity_list[i]. + entity_code, + ext_size); + } + } + } + + cudbg_hdr->data_len = total_size; + *outbuf_size = total_size; + + if (flag_ext) + *outbuf_size += ext_size; + + return 0; +err: + return rc; +} + +void reset_skip_entity(void) +{ + int i; + + for (i = 0; i < ARRAY_SIZE(large_entity_list); i++) + large_entity_list[i].skip_flag = 0; +} + +void skip_entity(int entity_code) +{ + int i; + for (i = 0; i < sizeof(large_entity_list) / sizeof(struct large_entity); + i++) { + if (large_entity_list[i].entity_code == entity_code) + large_entity_list[i].skip_flag = 1; + } +} + +int is_large_entity(int entity_code) +{ + int i; + + for (i = 0; i < sizeof(large_entity_list) / sizeof(struct large_entity); + i++) { + if (large_entity_list[i].entity_code == entity_code) + return 1; + } + return 0; +} + +int get_entity_hdr(void *outbuf, int i, u32 size, + struct cudbg_entity_hdr **entity_hdr) +{ + int rc = 0; + struct cudbg_hdr *cudbg_hdr = (struct cudbg_hdr *)outbuf; + + if (cudbg_hdr->hdr_len + (sizeof(struct cudbg_entity_hdr)*i) > size) + return CUDBG_STATUS_SMALL_BUFF; + + *entity_hdr = (struct cudbg_entity_hdr *) + ((char *)outbuf+cudbg_hdr->hdr_len + + (sizeof(struct cudbg_entity_hdr)*(i-1))); + return rc; +} + +static int collect_rss(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + u32 size; + int rc = 0; + + size = RSS_NENTRIES * sizeof(u16); + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + rc = t4_read_rss(padap, (u16 *)scratch_buff.data); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s(), t4_read_rss failed!, rc: %d\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_sw_state(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct sw_state *swstate; + u32 size; + int rc = 0; + + size = sizeof(struct sw_state); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + swstate = (struct sw_state *) scratch_buff.data; + + swstate->fw_state = t4_read_reg(padap, A_PCIE_FW); + snprintf(swstate->caller_string, sizeof(swstate->caller_string), "%s", + "FreeBSD"); + swstate->os_type = 0; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_ddp_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct tp_usm_stats *tp_usm_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct tp_usm_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tp_usm_stats_buff = (struct tp_usm_stats *) scratch_buff.data; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_get_usm_stats(padap, tp_usm_stats_buff, 1); + /* spin_unlock(&padap->stats_lock); TODO*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_ulptx_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_ulptx_la *ulptx_la_buff; + u32 size, i, j; + int rc = 0; + + size = sizeof(struct struct_ulptx_la); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + ulptx_la_buff = (struct struct_ulptx_la *) scratch_buff.data; + + for (i = 0; i < CUDBG_NUM_ULPTX; i++) { + ulptx_la_buff->rdptr[i] = t4_read_reg(padap, + A_ULP_TX_LA_RDPTR_0 + + 0x10 * i); + ulptx_la_buff->wrptr[i] = t4_read_reg(padap, + A_ULP_TX_LA_WRPTR_0 + + 0x10 * i); + ulptx_la_buff->rddata[i] = t4_read_reg(padap, + A_ULP_TX_LA_RDDATA_0 + + 0x10 * i); + for (j = 0; j < CUDBG_NUM_ULPTX_READ; j++) { + ulptx_la_buff->rd_data[i][j] = + t4_read_reg(padap, + A_ULP_TX_LA_RDDATA_0 + 0x10 * i); + } + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; + +} + +static int collect_ulprx_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_ulprx_la *ulprx_la_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_ulprx_la); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + ulprx_la_buff = (struct struct_ulprx_la *) scratch_buff.data; + t4_ulprx_read_la(padap, (u32 *)ulprx_la_buff->data); + ulprx_la_buff->size = ULPRX_LA_SIZE; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_cpl_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_tp_cpl_stats *tp_cpl_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_tp_cpl_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tp_cpl_stats_buff = (struct struct_tp_cpl_stats *) scratch_buff.data; + tp_cpl_stats_buff->nchan = padap->chip_params->nchan; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_tp_get_cpl_stats(padap, &tp_cpl_stats_buff->stats, 1); + /* spin_unlock(&padap->stats_lock); TODO*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_wc_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_wc_stats *wc_stats_buff; + u32 val1; + u32 val2; + u32 size; + + int rc = 0; + + size = sizeof(struct struct_wc_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + wc_stats_buff = (struct struct_wc_stats *) scratch_buff.data; + + if (!is_t4(padap)) { + val1 = t4_read_reg(padap, A_SGE_STAT_TOTAL); + val2 = t4_read_reg(padap, A_SGE_STAT_MATCH); + wc_stats_buff->wr_cl_success = val1 - val2; + wc_stats_buff->wr_cl_fail = val2; + } else { + wc_stats_buff->wr_cl_success = 0; + wc_stats_buff->wr_cl_fail = 0; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int mem_desc_cmp(const void *a, const void *b) +{ + return ((const struct struct_mem_desc *)a)->base - + ((const struct struct_mem_desc *)b)->base; +} + +static int fill_meminfo(struct adapter *padap, + struct struct_meminfo *meminfo_buff) +{ + struct struct_mem_desc *md; + u32 size, lo, hi; + u32 used, alloc; + int n, i, rc = 0; + + size = sizeof(struct struct_meminfo); + + memset(meminfo_buff->avail, 0, + ARRAY_SIZE(meminfo_buff->avail) * + sizeof(struct struct_mem_desc)); + memset(meminfo_buff->mem, 0, + (ARRAY_SIZE(region) + 3) * sizeof(struct struct_mem_desc)); + md = meminfo_buff->mem; + + for (i = 0; i < ARRAY_SIZE(meminfo_buff->mem); i++) { + meminfo_buff->mem[i].limit = 0; + meminfo_buff->mem[i].idx = i; + } + + i = 0; + + lo = t4_read_reg(padap, A_MA_TARGET_MEM_ENABLE); + + if (lo & F_EDRAM0_ENABLE) { + hi = t4_read_reg(padap, A_MA_EDRAM0_BAR); + meminfo_buff->avail[i].base = G_EDRAM0_BASE(hi) << 20; + meminfo_buff->avail[i].limit = meminfo_buff->avail[i].base + + (G_EDRAM0_SIZE(hi) << 20); + meminfo_buff->avail[i].idx = 0; + i++; + } + + if (lo & F_EDRAM1_ENABLE) { + hi = t4_read_reg(padap, A_MA_EDRAM1_BAR); + meminfo_buff->avail[i].base = G_EDRAM1_BASE(hi) << 20; + meminfo_buff->avail[i].limit = meminfo_buff->avail[i].base + + (G_EDRAM1_SIZE(hi) << 20); + meminfo_buff->avail[i].idx = 1; + i++; + } + + if (is_t5(padap)) { + if (lo & F_EXT_MEM0_ENABLE) { + hi = t4_read_reg(padap, A_MA_EXT_MEMORY0_BAR); + meminfo_buff->avail[i].base = G_EXT_MEM_BASE(hi) << 20; + meminfo_buff->avail[i].limit = + meminfo_buff->avail[i].base + + (G_EXT_MEM_SIZE(hi) << 20); + meminfo_buff->avail[i].idx = 3; + i++; + } + + if (lo & F_EXT_MEM1_ENABLE) { + hi = t4_read_reg(padap, A_MA_EXT_MEMORY1_BAR); + meminfo_buff->avail[i].base = G_EXT_MEM1_BASE(hi) << 20; + meminfo_buff->avail[i].limit = + meminfo_buff->avail[i].base + + (G_EXT_MEM1_SIZE(hi) << 20); + meminfo_buff->avail[i].idx = 4; + i++; + } + } else if (is_t6(padap)) { + if (lo & F_EXT_MEM_ENABLE) { + hi = t4_read_reg(padap, A_MA_EXT_MEMORY_BAR); + meminfo_buff->avail[i].base = G_EXT_MEM_BASE(hi) << 20; + meminfo_buff->avail[i].limit = + meminfo_buff->avail[i].base + + (G_EXT_MEM_SIZE(hi) << 20); + meminfo_buff->avail[i].idx = 2; + i++; + } + } + + if (!i) { /* no memory available */ + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + goto err; + } + + meminfo_buff->avail_c = i; + qsort(meminfo_buff->avail, i, sizeof(struct struct_mem_desc), + mem_desc_cmp); + (md++)->base = t4_read_reg(padap, A_SGE_DBQ_CTXT_BADDR); + (md++)->base = t4_read_reg(padap, A_SGE_IMSG_CTXT_BADDR); + (md++)->base = t4_read_reg(padap, A_SGE_FLM_CACHE_BADDR); + (md++)->base = t4_read_reg(padap, A_TP_CMM_TCB_BASE); + (md++)->base = t4_read_reg(padap, A_TP_CMM_MM_BASE); + (md++)->base = t4_read_reg(padap, A_TP_CMM_TIMER_BASE); + (md++)->base = t4_read_reg(padap, A_TP_CMM_MM_RX_FLST_BASE); + (md++)->base = t4_read_reg(padap, A_TP_CMM_MM_TX_FLST_BASE); + (md++)->base = t4_read_reg(padap, A_TP_CMM_MM_PS_FLST_BASE); + + /* the next few have explicit upper bounds */ + md->base = t4_read_reg(padap, A_TP_PMM_TX_BASE); + md->limit = md->base - 1 + + t4_read_reg(padap, + A_TP_PMM_TX_PAGE_SIZE) * + G_PMTXMAXPAGE(t4_read_reg(padap, + A_TP_PMM_TX_MAX_PAGE) + ); + md++; + + md->base = t4_read_reg(padap, A_TP_PMM_RX_BASE); + md->limit = md->base - 1 + + t4_read_reg(padap, + A_TP_PMM_RX_PAGE_SIZE) * + G_PMRXMAXPAGE(t4_read_reg(padap, + A_TP_PMM_RX_MAX_PAGE) + ); + md++; + if (t4_read_reg(padap, A_LE_DB_CONFIG) & F_HASHEN) { + if (chip_id(padap) <= CHELSIO_T5) { + hi = t4_read_reg(padap, A_LE_DB_TID_HASHBASE) / 4; + md->base = t4_read_reg(padap, A_LE_DB_HASH_TID_BASE); + } else { + hi = t4_read_reg(padap, A_LE_DB_HASH_TID_BASE); + md->base = t4_read_reg(padap, + A_LE_DB_HASH_TBL_BASE_ADDR); + } + md->limit = 0; + } else { + md->base = 0; + md->idx = ARRAY_SIZE(region); /* hide it */ + } + md++; +#define ulp_region(reg) \ + {\ + md->base = t4_read_reg(padap, A_ULP_ ## reg ## _LLIMIT);\ + (md++)->limit = t4_read_reg(padap, A_ULP_ ## reg ## _ULIMIT);\ + } + + ulp_region(RX_ISCSI); + ulp_region(RX_TDDP); + ulp_region(TX_TPT); + ulp_region(RX_STAG); + ulp_region(RX_RQ); + ulp_region(RX_RQUDP); + ulp_region(RX_PBL); + ulp_region(TX_PBL); +#undef ulp_region + md->base = 0; + md->idx = ARRAY_SIZE(region); + if (!is_t4(padap)) { + u32 sge_ctrl = t4_read_reg(padap, A_SGE_CONTROL2); + u32 fifo_size = t4_read_reg(padap, A_SGE_DBVFIFO_SIZE); + if (is_t5(padap)) { + if (sge_ctrl & F_VFIFO_ENABLE) + size = G_DBVFIFO_SIZE(fifo_size); + } else + size = G_T6_DBVFIFO_SIZE(fifo_size); + + if (size) { + md->base = G_BASEADDR(t4_read_reg(padap, + A_SGE_DBVFIFO_BADDR)); + md->limit = md->base + (size << 2) - 1; + } + } + + md++; + + md->base = t4_read_reg(padap, A_ULP_RX_CTX_BASE); + md->limit = 0; + md++; + md->base = t4_read_reg(padap, A_ULP_TX_ERR_TABLE_BASE); + md->limit = 0; + md++; +#ifndef __NO_DRIVER_OCQ_SUPPORT__ + /*md->base = padap->vres.ocq.start;*/ + /*if (adap->vres.ocq.size)*/ + /* md->limit = md->base + adap->vres.ocq.size - 1;*/ + /*else*/ + md->idx = ARRAY_SIZE(region); /* hide it */ + md++; +#endif + + /* add any address-space holes, there can be up to 3 */ + for (n = 0; n < i - 1; n++) + if (meminfo_buff->avail[n].limit < + meminfo_buff->avail[n + 1].base) + (md++)->base = meminfo_buff->avail[n].limit; + + if (meminfo_buff->avail[n].limit) + (md++)->base = meminfo_buff->avail[n].limit; + + n = (int) (md - meminfo_buff->mem); + meminfo_buff->mem_c = n; + + qsort(meminfo_buff->mem, n, sizeof(struct struct_mem_desc), + mem_desc_cmp); + + lo = t4_read_reg(padap, A_CIM_SDRAM_BASE_ADDR); + hi = t4_read_reg(padap, A_CIM_SDRAM_ADDR_SIZE) + lo - 1; + meminfo_buff->up_ram_lo = lo; + meminfo_buff->up_ram_hi = hi; + + lo = t4_read_reg(padap, A_CIM_EXTMEM2_BASE_ADDR); + hi = t4_read_reg(padap, A_CIM_EXTMEM2_ADDR_SIZE) + lo - 1; + meminfo_buff->up_extmem2_lo = lo; + meminfo_buff->up_extmem2_hi = hi; + + lo = t4_read_reg(padap, A_TP_PMM_RX_MAX_PAGE); + meminfo_buff->rx_pages_data[0] = G_PMRXMAXPAGE(lo); + meminfo_buff->rx_pages_data[1] = + t4_read_reg(padap, A_TP_PMM_RX_PAGE_SIZE) >> 10; + meminfo_buff->rx_pages_data[2] = (lo & F_PMRXNUMCHN) ? 2 : 1 ; + + lo = t4_read_reg(padap, A_TP_PMM_TX_MAX_PAGE); + hi = t4_read_reg(padap, A_TP_PMM_TX_PAGE_SIZE); + meminfo_buff->tx_pages_data[0] = G_PMTXMAXPAGE(lo); + meminfo_buff->tx_pages_data[1] = + hi >= (1 << 20) ? (hi >> 20) : (hi >> 10); + meminfo_buff->tx_pages_data[2] = + hi >= (1 << 20) ? 'M' : 'K'; + meminfo_buff->tx_pages_data[3] = 1 << G_PMTXNUMCHN(lo); + + for (i = 0; i < 4; i++) { + if (chip_id(padap) > CHELSIO_T5) + lo = t4_read_reg(padap, + A_MPS_RX_MAC_BG_PG_CNT0 + i * 4); + else + lo = t4_read_reg(padap, A_MPS_RX_PG_RSV0 + i * 4); + if (is_t5(padap)) { + used = G_T5_USED(lo); + alloc = G_T5_ALLOC(lo); + } else { + used = G_USED(lo); + alloc = G_ALLOC(lo); + } + meminfo_buff->port_used[i] = used; + meminfo_buff->port_alloc[i] = alloc; + } + + for (i = 0; i < padap->chip_params->nchan; i++) { + if (chip_id(padap) > CHELSIO_T5) + lo = t4_read_reg(padap, + A_MPS_RX_LPBK_BG_PG_CNT0 + i * 4); + else + lo = t4_read_reg(padap, A_MPS_RX_PG_RSV4 + i * 4); + if (is_t5(padap)) { + used = G_T5_USED(lo); + alloc = G_T5_ALLOC(lo); + } else { + used = G_USED(lo); + alloc = G_ALLOC(lo); + } + meminfo_buff->loopback_used[i] = used; + meminfo_buff->loopback_alloc[i] = alloc; + } +err: + return rc; +} + +static int collect_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_meminfo *meminfo_buff; + int rc = 0; + u32 size; + + size = sizeof(struct struct_meminfo); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + meminfo_buff = (struct struct_meminfo *)scratch_buff.data; + + rc = fill_meminfo(padap, meminfo_buff); + if (rc) + goto err; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_lb_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct lb_port_stats *tmp_stats; + struct struct_lb_stats *lb_stats_buff; + u32 i, n, size; + int rc = 0; + + rc = padap->params.nports; + if (rc < 0) + goto err; + + n = rc; + size = sizeof(struct struct_lb_stats) + + n * sizeof(struct lb_port_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + lb_stats_buff = (struct struct_lb_stats *) scratch_buff.data; + + lb_stats_buff->nchan = n; + tmp_stats = lb_stats_buff->s; + + for (i = 0; i < n; i += 2, tmp_stats += 2) { + t4_get_lb_stats(padap, i, tmp_stats); + t4_get_lb_stats(padap, i + 1, tmp_stats+1); + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_rdma_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_er) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct tp_rdma_stats *rdma_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct tp_rdma_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + rdma_stats_buff = (struct tp_rdma_stats *) scratch_buff.data; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_tp_get_rdma_stats(padap, rdma_stats_buff, 1); + /* spin_unlock(&padap->stats_lock); TODO*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_clk_info(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct struct_clk_info *clk_info_buff; + u64 tp_tick_us; + int size; + int rc = 0; + + if (!padap->params.vpd.cclk) { + rc = CUDBG_STATUS_CCLK_NOT_DEFINED; + goto err; + } + + size = sizeof(struct struct_clk_info); + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + clk_info_buff = (struct struct_clk_info *) scratch_buff.data; + + clk_info_buff->cclk_ps = 1000000000 / padap->params.vpd.cclk; /* in ps + */ + clk_info_buff->res = t4_read_reg(padap, A_TP_TIMER_RESOLUTION); + clk_info_buff->tre = G_TIMERRESOLUTION(clk_info_buff->res); + clk_info_buff->dack_re = G_DELAYEDACKRESOLUTION(clk_info_buff->res); + tp_tick_us = (clk_info_buff->cclk_ps << clk_info_buff->tre) / 1000000; + /* in us */ + clk_info_buff->dack_timer = ((clk_info_buff->cclk_ps << + clk_info_buff->dack_re) / 1000000) * + t4_read_reg(padap, A_TP_DACK_TIMER); + + clk_info_buff->retransmit_min = + tp_tick_us * t4_read_reg(padap, A_TP_RXT_MIN); + clk_info_buff->retransmit_max = + tp_tick_us * t4_read_reg(padap, A_TP_RXT_MAX); + + clk_info_buff->persist_timer_min = + tp_tick_us * t4_read_reg(padap, A_TP_PERS_MIN); + clk_info_buff->persist_timer_max = + tp_tick_us * t4_read_reg(padap, A_TP_PERS_MAX); + + clk_info_buff->keepalive_idle_timer = + tp_tick_us * t4_read_reg(padap, A_TP_KEEP_IDLE); + clk_info_buff->keepalive_interval = + tp_tick_us * t4_read_reg(padap, A_TP_KEEP_INTVL); + + clk_info_buff->initial_srtt = + tp_tick_us * G_INITSRTT(t4_read_reg(padap, A_TP_INIT_SRTT)); + clk_info_buff->finwait2_timer = + tp_tick_us * t4_read_reg(padap, A_TP_FINWAIT2_TIMER); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; + +} + +static int collect_macstats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_mac_stats_rev1 *mac_stats_buff; + u32 i, n, size; + int rc = 0; + + rc = padap->params.nports; + if (rc < 0) + goto err; + + n = rc; + size = sizeof(struct struct_mac_stats_rev1); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + mac_stats_buff = (struct struct_mac_stats_rev1 *) scratch_buff.data; + + mac_stats_buff->ver_hdr.signature = CUDBG_ENTITY_SIGNATURE; + mac_stats_buff->ver_hdr.revision = CUDBG_MAC_STATS_REV; + mac_stats_buff->ver_hdr.size = sizeof(struct struct_mac_stats_rev1) - + sizeof(struct cudbg_ver_hdr); + + mac_stats_buff->port_count = n; + for (i = 0; i < mac_stats_buff->port_count; i++) + t4_get_port_stats(padap, i, &mac_stats_buff->stats[i]); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_cim_pif_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct cim_pif_la *cim_pif_la_buff; + u32 size; + int rc = 0; + + size = sizeof(struct cim_pif_la) + + 2 * CIM_PIFLA_SIZE * 6 * sizeof(u32); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + cim_pif_la_buff = (struct cim_pif_la *) scratch_buff.data; + cim_pif_la_buff->size = CIM_PIFLA_SIZE; + + t4_cim_read_pif_la(padap, (u32 *)cim_pif_la_buff->data, + (u32 *)cim_pif_la_buff->data + 6 * CIM_PIFLA_SIZE, + NULL, NULL); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_tp_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_tp_la *tp_la_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_tp_la) + TPLA_SIZE * sizeof(u64); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tp_la_buff = (struct struct_tp_la *) scratch_buff.data; + + tp_la_buff->mode = G_DBGLAMODE(t4_read_reg(padap, A_TP_DBG_LA_CONFIG)); + t4_tp_read_la(padap, (u64 *)tp_la_buff->data, NULL); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_fcoe_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_tp_fcoe_stats *tp_fcoe_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_tp_fcoe_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tp_fcoe_stats_buff = (struct struct_tp_fcoe_stats *) scratch_buff.data; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_get_fcoe_stats(padap, 0, &tp_fcoe_stats_buff->stats[0], 1); + t4_get_fcoe_stats(padap, 1, &tp_fcoe_stats_buff->stats[1], 1); + if (padap->chip_params->nchan == NCHAN) { + t4_get_fcoe_stats(padap, 2, &tp_fcoe_stats_buff->stats[2], 1); + t4_get_fcoe_stats(padap, 3, &tp_fcoe_stats_buff->stats[3], 1); + } + /* spin_unlock(&padap->stats_lock); TODO*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_tp_err_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_tp_err_stats *tp_err_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_tp_err_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tp_err_stats_buff = (struct struct_tp_err_stats *) scratch_buff.data; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_tp_get_err_stats(padap, &tp_err_stats_buff->stats, 1); + /* spin_unlock(&padap->stats_lock); TODO*/ + tp_err_stats_buff->nchan = padap->chip_params->nchan; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_tcp_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_tcp_stats *tcp_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_tcp_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + tcp_stats_buff = (struct struct_tcp_stats *) scratch_buff.data; + + /* spin_lock(&padap->stats_lock); TODO*/ + t4_tp_get_tcp_stats(padap, &tcp_stats_buff->v4, &tcp_stats_buff->v6, 1); + /* spin_unlock(&padap->stats_lock); TODO*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_hw_sched(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_hw_sched *hw_sched_buff; + u32 size; + int i, rc = 0; + + if (!padap->params.vpd.cclk) { + rc = CUDBG_STATUS_CCLK_NOT_DEFINED; + goto err; + } + + size = sizeof(struct struct_hw_sched); + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + hw_sched_buff = (struct struct_hw_sched *) scratch_buff.data; + + hw_sched_buff->map = t4_read_reg(padap, A_TP_TX_MOD_QUEUE_REQ_MAP); + hw_sched_buff->mode = G_TIMERMODE(t4_read_reg(padap, A_TP_MOD_CONFIG)); + t4_read_pace_tbl(padap, hw_sched_buff->pace_tab); + + for (i = 0; i < NTX_SCHED; ++i) { + t4_get_tx_sched(padap, i, &hw_sched_buff->kbps[i], + &hw_sched_buff->ipg[i], 1); + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_pm_stats(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct struct_pm_stats *pm_stats_buff; + u32 size; + int rc = 0; + + size = sizeof(struct struct_pm_stats); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + pm_stats_buff = (struct struct_pm_stats *) scratch_buff.data; + + t4_pmtx_get_stats(padap, pm_stats_buff->tx_cnt, pm_stats_buff->tx_cyc); + t4_pmrx_get_stats(padap, pm_stats_buff->rx_cnt, pm_stats_buff->rx_cyc); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_path_mtu(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + u32 size; + int rc = 0; + + size = NMTUS * sizeof(u16); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + t4_read_mtu_tbl(padap, (u16 *)scratch_buff.data, NULL); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_rss_key(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + u32 size; + + int rc = 0; + + size = 10 * sizeof(u32); + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + t4_read_rss_key(padap, (u32 *)scratch_buff.data, 1); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_rss_config(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct rss_config *rss_conf; + int rc; + u32 size; + + size = sizeof(struct rss_config); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + rss_conf = (struct rss_config *)scratch_buff.data; + + rss_conf->tp_rssconf = t4_read_reg(padap, A_TP_RSS_CONFIG); + rss_conf->tp_rssconf_tnl = t4_read_reg(padap, A_TP_RSS_CONFIG_TNL); + rss_conf->tp_rssconf_ofd = t4_read_reg(padap, A_TP_RSS_CONFIG_OFD); + rss_conf->tp_rssconf_syn = t4_read_reg(padap, A_TP_RSS_CONFIG_SYN); + rss_conf->tp_rssconf_vrt = t4_read_reg(padap, A_TP_RSS_CONFIG_VRT); + rss_conf->tp_rssconf_cng = t4_read_reg(padap, A_TP_RSS_CONFIG_CNG); + rss_conf->chip = padap->params.chipid; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_rss_vf_config(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + struct rss_vf_conf *vfconf; + int vf, rc, vf_count; + u32 size; + + vf_count = padap->chip_params->vfcount; + size = vf_count * sizeof(*vfconf); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + vfconf = (struct rss_vf_conf *)scratch_buff.data; + + for (vf = 0; vf < vf_count; vf++) { + t4_read_rss_vf_config(padap, vf, &vfconf[vf].rss_vf_vfl, + &vfconf[vf].rss_vf_vfh, 1); + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_rss_pf_config(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct rss_pf_conf *pfconf; + struct adapter *padap = pdbg_init->adap; + u32 rss_pf_map, rss_pf_mask, size; + int pf, rc; + + size = 8 * sizeof(*pfconf); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + pfconf = (struct rss_pf_conf *)scratch_buff.data; + + rss_pf_map = t4_read_rss_pf_map(padap, 1); + rss_pf_mask = t4_read_rss_pf_mask(padap, 1); + + for (pf = 0; pf < 8; pf++) { + pfconf[pf].rss_pf_map = rss_pf_map; + pfconf[pf].rss_pf_mask = rss_pf_mask; + /* no return val */ + t4_read_rss_pf_config(padap, pf, &pfconf[pf].rss_pf_config, 1); + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int check_valid(u32 *buf, int type) +{ + int index; + int bit; + int bit_pos = 0; + + switch (type) { + case CTXT_EGRESS: + bit_pos = 176; + break; + case CTXT_INGRESS: + bit_pos = 141; + break; + case CTXT_FLM: + bit_pos = 89; + break; + } + index = bit_pos / 32; + bit = bit_pos % 32; + + return buf[index] & (1U << bit); +} + +/** + * Get EGRESS, INGRESS, FLM, and CNM max qid. + * + * For EGRESS and INGRESS, do the following calculation. + * max_qid = (DBQ/IMSG context region size in bytes) / + * (size of context in bytes). + * + * For FLM, do the following calculation. + * max_qid = (FLM cache region size in bytes) / + * ((number of pointers cached in EDRAM) * 8 (bytes per pointer)). + * + * There's a 1-to-1 mapping between FLM and CNM if there's no header splitting + * enabled; i.e., max CNM qid is equal to max FLM qid. However, if header + * splitting is enabled, then max CNM qid is half of max FLM qid. + */ +static int get_max_ctxt_qid(struct adapter *padap, + struct struct_meminfo *meminfo, + u32 *max_ctx_qid, u8 nelem) +{ + u32 i, idx, found = 0; + + if (nelem != (CTXT_CNM + 1)) + return -EINVAL; + + for (i = 0; i < meminfo->mem_c; i++) { + if (meminfo->mem[i].idx >= ARRAY_SIZE(region)) + continue; /* skip holes */ + + idx = meminfo->mem[i].idx; + /* Get DBQ, IMSG, and FLM context region size */ + if (idx <= CTXT_FLM) { + if (!(meminfo->mem[i].limit)) + meminfo->mem[i].limit = + i < meminfo->mem_c - 1 ? + meminfo->mem[i + 1].base - 1 : ~0; + + if (idx < CTXT_FLM) { + /* Get EGRESS and INGRESS max qid. */ + max_ctx_qid[idx] = (meminfo->mem[i].limit - + meminfo->mem[i].base + 1) / + CUDBG_CTXT_SIZE_BYTES; + found++; + } else { + /* Get FLM and CNM max qid. */ + u32 value, edram_ptr_count; + u8 bytes_per_ptr = 8; + u8 nohdr; + + value = t4_read_reg(padap, A_SGE_FLM_CFG); + + /* Check if header splitting is enabled. */ + nohdr = (value >> S_NOHDR) & 1U; + + /* Get the number of pointers in EDRAM per + * qid in units of 32. + */ + edram_ptr_count = 32 * + (1U << G_EDRAMPTRCNT(value)); + + /* EDRAMPTRCNT value of 3 is reserved. + * So don't exceed 128. + */ + if (edram_ptr_count > 128) + edram_ptr_count = 128; + + max_ctx_qid[idx] = (meminfo->mem[i].limit - + meminfo->mem[i].base + 1) / + (edram_ptr_count * + bytes_per_ptr); + found++; + + /* CNM has 1-to-1 mapping with FLM. + * However, if header splitting is enabled, + * then max CNM qid is half of max FLM qid. + */ + max_ctx_qid[CTXT_CNM] = nohdr ? + max_ctx_qid[idx] : + max_ctx_qid[idx] >> 1; + + /* One more increment for CNM */ + found++; + } + } + if (found == nelem) + break; + } + + /* Sanity check. Ensure the values are within known max. */ + max_ctx_qid[CTXT_EGRESS] = min_t(u32, max_ctx_qid[CTXT_EGRESS], + M_CTXTQID); + max_ctx_qid[CTXT_INGRESS] = min_t(u32, max_ctx_qid[CTXT_INGRESS], + CUDBG_MAX_INGRESS_QIDS); + max_ctx_qid[CTXT_FLM] = min_t(u32, max_ctx_qid[CTXT_FLM], + CUDBG_MAX_FL_QIDS); + max_ctx_qid[CTXT_CNM] = min_t(u32, max_ctx_qid[CTXT_CNM], + CUDBG_MAX_CNM_QIDS); + return 0; +} + +static int collect_dump_context(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct cudbg_buffer temp_buff; + struct adapter *padap = pdbg_init->adap; + u32 size = 0, next_offset = 0, total_size = 0; + struct cudbg_ch_cntxt *buff = NULL; + struct struct_meminfo meminfo; + int bytes = 0; + int rc = 0; + u32 i, j; + u32 max_ctx_qid[CTXT_CNM + 1]; + bool limit_qid = false; + u32 qid_count = 0; + + rc = fill_meminfo(padap, &meminfo); + if (rc) + goto err; + + /* Get max valid qid for each type of queue */ + rc = get_max_ctxt_qid(padap, &meminfo, max_ctx_qid, CTXT_CNM + 1); + if (rc) + goto err; + + /* There are four types of queues. Collect context upto max + * qid of each type of queue. + */ + for (i = CTXT_EGRESS; i <= CTXT_CNM; i++) + size += sizeof(struct cudbg_ch_cntxt) * max_ctx_qid[i]; + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc == CUDBG_STATUS_NO_SCRATCH_MEM) { + /* Not enough scratch Memory available. + * Collect context of at least CUDBG_LOWMEM_MAX_CTXT_QIDS + * for each queue type. + */ + size = 0; + for (i = CTXT_EGRESS; i <= CTXT_CNM; i++) + size += sizeof(struct cudbg_ch_cntxt) * + CUDBG_LOWMEM_MAX_CTXT_QIDS; + + limit_qid = true; + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + } + + buff = (struct cudbg_ch_cntxt *)scratch_buff.data; + + /* Collect context data */ + for (i = CTXT_EGRESS; i <= CTXT_FLM; i++) { + qid_count = 0; + for (j = 0; j < max_ctx_qid[i]; j++) { + read_sge_ctxt(pdbg_init, j, i, buff->data); + + rc = check_valid(buff->data, i); + if (rc) { + buff->cntxt_type = i; + buff->cntxt_id = j; + buff++; + total_size += sizeof(struct cudbg_ch_cntxt); + + if (i == CTXT_FLM) { + read_sge_ctxt(pdbg_init, j, CTXT_CNM, + buff->data); + buff->cntxt_type = CTXT_CNM; + buff->cntxt_id = j; + buff++; + total_size += + sizeof(struct cudbg_ch_cntxt); + } + qid_count++; + } + + /* If there's not enough space to collect more qids, + * then bail and move on to next queue type. + */ + if (limit_qid && + qid_count >= CUDBG_LOWMEM_MAX_CTXT_QIDS) + break; + } + } + + scratch_buff.size = total_size; + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + /* Splitting buffer and writing in terms of CUDBG_CHUNK_SIZE */ + while (total_size > 0) { + bytes = min_t(unsigned long, (unsigned long)total_size, + (unsigned long)CUDBG_CHUNK_SIZE); + temp_buff.size = bytes; + temp_buff.data = (void *)((char *)scratch_buff.data + + next_offset); + + rc = compress_buff(&temp_buff, dbg_buff); + if (rc) + goto err1; + + total_size -= bytes; + next_offset += bytes; + } + +err1: + scratch_buff.size = size; + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_fw_devlog(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ +#ifdef notyet + struct adapter *padap = pdbg_init->adap; + struct devlog_params *dparams = &padap->params.devlog; + struct cudbg_param *params = NULL; + struct cudbg_buffer scratch_buff; + u32 offset; + int rc = 0, i; + + rc = t4_init_devlog_params(padap, 1); + + if (rc < 0) { + pdbg_init->print("%s(), t4_init_devlog_params failed!, rc: "\ + "%d\n", __func__, rc); + for (i = 0; i < pdbg_init->dbg_params_cnt; i++) { + if (pdbg_init->dbg_params[i].param_type == + CUDBG_DEVLOG_PARAM) { + params = &pdbg_init->dbg_params[i]; + break; + } + } + + if (params) { + dparams->memtype = params->u.devlog_param.memtype; + dparams->start = params->u.devlog_param.start; + dparams->size = params->u.devlog_param.size; + } else { + cudbg_err->sys_err = rc; + goto err; + } + } + + rc = get_scratch_buff(dbg_buff, dparams->size, &scratch_buff); + + if (rc) + goto err; + + /* Collect FW devlog */ + if (dparams->start != 0) { + offset = scratch_buff.offset; + rc = t4_memory_rw(padap, padap->params.drv_memwin, + dparams->memtype, dparams->start, + dparams->size, + (__be32 *)((char *)scratch_buff.data + + offset), 1); + + if (rc) { + pdbg_init->print("%s(), t4_memory_rw failed!, rc: "\ + "%d\n", __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +#endif + return (EDOOFUS); +} +/* CIM OBQ */ + +static int collect_cim_obq_ulp0(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 0; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_cim_obq_ulp1(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 1; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_cim_obq_ulp2(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 2; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_cim_obq_ulp3(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 3; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_cim_obq_sge(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 4; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_cim_obq_ncsi(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 5; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_obq_sge_rx_q0(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 6; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int collect_obq_sge_rx_q1(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 7; + + rc = read_cim_obq(pdbg_init, dbg_buff, cudbg_err, qid); + + return rc; +} + +static int read_cim_obq(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err, int qid) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 qsize; + int rc; + int no_of_read_words; + + /* collect CIM OBQ */ + qsize = 6 * CIM_OBQ_SIZE * 4 * sizeof(u32); + rc = get_scratch_buff(dbg_buff, qsize, &scratch_buff); + if (rc) + goto err; + + /* t4_read_cim_obq will return no. of read words or error */ + no_of_read_words = t4_read_cim_obq(padap, qid, + (u32 *)((u32 *)scratch_buff.data + + scratch_buff.offset), qsize); + + /* no_of_read_words is less than or equal to 0 means error */ + if (no_of_read_words <= 0) { + if (no_of_read_words == 0) + rc = CUDBG_SYSTEM_ERROR; + else + rc = no_of_read_words; + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_read_cim_obq failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + scratch_buff.size = no_of_read_words * 4; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +/* CIM IBQ */ + +static int collect_cim_ibq_tp0(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 0; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int collect_cim_ibq_tp1(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 1; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int collect_cim_ibq_ulp(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 2; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int collect_cim_ibq_sge0(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 3; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int collect_cim_ibq_sge1(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc = 0, qid = 4; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int collect_cim_ibq_ncsi(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + int rc, qid = 5; + + rc = read_cim_ibq(pdbg_init, dbg_buff, cudbg_err, qid); + return rc; +} + +static int read_cim_ibq(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err, int qid) +{ + struct adapter *padap = pdbg_init->adap; + struct cudbg_buffer scratch_buff; + u32 qsize; + int rc; + int no_of_read_words; + + /* collect CIM IBQ */ + qsize = CIM_IBQ_SIZE * 4 * sizeof(u32); + rc = get_scratch_buff(dbg_buff, qsize, &scratch_buff); + + if (rc) + goto err; + + /* t4_read_cim_ibq will return no. of read words or error */ + no_of_read_words = t4_read_cim_ibq(padap, qid, + (u32 *)((u32 *)scratch_buff.data + + scratch_buff.offset), qsize); + /* no_of_read_words is less than or equal to 0 means error */ + if (no_of_read_words <= 0) { + if (no_of_read_words == 0) + rc = CUDBG_SYSTEM_ERROR; + else + rc = no_of_read_words; + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_read_cim_ibq failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + if (rc) + goto err1; + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); + +err: + return rc; +} + +static int collect_cim_ma_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 rc = 0; + + /* collect CIM MA LA */ + scratch_buff.size = 2 * CIM_MALA_SIZE * 5 * sizeof(u32); + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + /* no return */ + t4_cim_read_ma_la(padap, + (u32 *) ((char *)scratch_buff.data + + scratch_buff.offset), + (u32 *) ((char *)scratch_buff.data + + scratch_buff.offset + 5 * CIM_MALA_SIZE)); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_cim_la(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + + int rc; + u32 cfg = 0; + int size; + + /* collect CIM LA */ + if (is_t6(padap)) { + size = padap->params.cim_la_size / 10 + 1; + size *= 11 * sizeof(u32); + } else { + size = padap->params.cim_la_size / 8; + size *= 8 * sizeof(u32); + } + + size += sizeof(cfg); + + rc = get_scratch_buff(dbg_buff, size, &scratch_buff); + if (rc) + goto err; + + rc = t4_cim_read(padap, A_UP_UP_DBG_LA_CFG, 1, &cfg); + + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_cim_read failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + memcpy((char *)scratch_buff.data + scratch_buff.offset, &cfg, + sizeof(cfg)); + + rc = t4_cim_read_la(padap, + (u32 *) ((char *)scratch_buff.data + + scratch_buff.offset + sizeof(cfg)), NULL); + if (rc < 0) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_cim_read_la failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + if (rc) + goto err1; + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_cim_qcfg(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 offset; + int cim_num_obq, rc = 0; + + struct struct_cim_qcfg *cim_qcfg_data = NULL; + + rc = get_scratch_buff(dbg_buff, sizeof(struct struct_cim_qcfg), + &scratch_buff); + + if (rc) + goto err; + + offset = scratch_buff.offset; + + cim_num_obq = is_t4(padap) ? CIM_NUM_OBQ : CIM_NUM_OBQ_T5; + + cim_qcfg_data = + (struct struct_cim_qcfg *)((u8 *)((char *)scratch_buff.data + + offset)); + + rc = t4_cim_read(padap, A_UP_IBQ_0_RDADDR, + ARRAY_SIZE(cim_qcfg_data->stat), cim_qcfg_data->stat); + + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_cim_read IBQ_0_RDADDR failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + rc = t4_cim_read(padap, A_UP_OBQ_0_REALADDR, + ARRAY_SIZE(cim_qcfg_data->obq_wr), + cim_qcfg_data->obq_wr); + + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_cim_read OBQ_0_REALADDR failed (%d)\n", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + + /* no return val */ + t4_read_cimq_cfg(padap, + cim_qcfg_data->base, + cim_qcfg_data->size, + cim_qcfg_data->thres); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + if (rc) + goto err1; + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +/** + * Fetch the TX/RX payload regions start and end. + * + * @padap (IN): adapter handle. + * @mem_type (IN): EDC0, EDC1, MC/MC0/MC1. + * @mem_tot_len (IN): total length of @mem_type memory region to read. + * @payload_type (IN): TX or RX Payload. + * @reg_info (OUT): store the payload region info. + * + * Fetch the TX/RX payload region information from meminfo. + * However, reading from the @mem_type region starts at 0 and not + * from whatever base info is stored in meminfo. Hence, if the + * payload region exists, then calculate the payload region + * start and end wrt 0 and @mem_tot_len, respectively, and set + * @reg_info->exist to true. Otherwise, set @reg_info->exist to false. + */ +#ifdef notyet +static int get_payload_range(struct adapter *padap, u8 mem_type, + unsigned long mem_tot_len, u8 payload_type, + struct struct_region_info *reg_info) +{ + struct struct_meminfo meminfo; + struct struct_mem_desc mem_region; + struct struct_mem_desc payload; + u32 i, idx, found = 0; + u8 mc_type; + int rc; + + /* Get meminfo of all regions */ + rc = fill_meminfo(padap, &meminfo); + if (rc) + return rc; + + /* Extract the specified TX or RX Payload region range */ + memset(&payload, 0, sizeof(struct struct_mem_desc)); + for (i = 0; i < meminfo.mem_c; i++) { + if (meminfo.mem[i].idx >= ARRAY_SIZE(region)) + continue; /* skip holes */ + + idx = meminfo.mem[i].idx; + /* Get TX or RX Payload region start and end */ + if (idx == payload_type) { + if (!(meminfo.mem[i].limit)) + meminfo.mem[i].limit = + i < meminfo.mem_c - 1 ? + meminfo.mem[i + 1].base - 1 : ~0; + + memcpy(&payload, &meminfo.mem[i], sizeof(payload)); + found = 1; + break; + } + } + + /* If TX or RX Payload region is not found return error. */ + if (!found) + return -EINVAL; + + if (mem_type < MEM_MC) { + memcpy(&mem_region, &meminfo.avail[mem_type], + sizeof(mem_region)); + } else { + /* Check if both MC0 and MC1 exist by checking if a + * base address for the specified @mem_type exists. + * If a base address exists, then there is MC1 and + * hence use the base address stored at index 3. + * Otherwise, use the base address stored at index 2. + */ + mc_type = meminfo.avail[mem_type].base ? + mem_type : mem_type - 1; + memcpy(&mem_region, &meminfo.avail[mc_type], + sizeof(mem_region)); + } + + /* Check if payload region exists in current memory */ + if (payload.base < mem_region.base && payload.limit < mem_region.base) { + reg_info->exist = false; + return 0; + } + + /* Get Payload region start and end with respect to 0 and + * mem_tot_len, respectively. This is because reading from the + * memory region starts at 0 and not at base info stored in meminfo. + */ + if (payload.base < mem_region.limit) { + reg_info->exist = true; + if (payload.base >= mem_region.base) + reg_info->start = payload.base - mem_region.base; + else + reg_info->start = 0; + + if (payload.limit < mem_region.limit) + reg_info->end = payload.limit - mem_region.base; + else + reg_info->end = mem_tot_len; + } + + return 0; +} +#endif + +static int read_fw_mem(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, u8 mem_type, + unsigned long tot_len, struct cudbg_error *cudbg_err) +{ +#ifdef notyet + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + unsigned long bytes_read = 0; + unsigned long bytes_left; + unsigned long bytes; + int rc; + struct struct_region_info payload[2]; /* TX and RX Payload Region */ + u16 get_payload_flag; + u8 i; + + get_payload_flag = + pdbg_init->dbg_params[CUDBG_GET_PAYLOAD_PARAM].param_type; + + /* If explicitly asked to get TX/RX Payload data, + * then don't zero out the payload data. Otherwise, + * zero out the payload data. + */ + if (!get_payload_flag) { + u8 region_index[2]; + u8 j = 0; + + /* Find the index of TX and RX Payload regions in meminfo */ + for (i = 0; i < ARRAY_SIZE(region); i++) { + if (!strcmp(region[i], "Tx payload:") || + !strcmp(region[i], "Rx payload:")) { + region_index[j] = i; + j++; + if (j == 2) + break; + } + } + + /* Get TX/RX Payload region range if they exist */ + memset(payload, 0, ARRAY_SIZE(payload) * sizeof(payload[0])); + for (i = 0; i < ARRAY_SIZE(payload); i++) { + rc = get_payload_range(padap, mem_type, tot_len, + region_index[i], + &payload[i]); + if (rc) + goto err; + + if (payload[i].exist) { + /* Align start and end to avoid wrap around */ + payload[i].start = + roundup(payload[i].start, + CUDBG_CHUNK_SIZE); + payload[i].end = + rounddown(payload[i].end, + CUDBG_CHUNK_SIZE); + } + } + } + + bytes_left = tot_len; + scratch_buff.size = tot_len; + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err; + + while (bytes_left > 0) { + bytes = min_t(unsigned long, bytes_left, (unsigned long)CUDBG_CHUNK_SIZE); + rc = get_scratch_buff(dbg_buff, bytes, &scratch_buff); + + if (rc) { + rc = CUDBG_STATUS_NO_SCRATCH_MEM; + goto err; + } + + if (!get_payload_flag) { + for (i = 0; i < ARRAY_SIZE(payload); i++) { + if (payload[i].exist && + bytes_read >= payload[i].start && + (bytes_read + bytes) <= payload[i].end) { + memset(scratch_buff.data, 0, bytes); + /* TX and RX Payload regions + * can't overlap. + */ + goto skip_read; + } + } + } + + /* Read from file */ + /*fread(scratch_buff.data, 1, Bytes, in);*/ + rc = t4_memory_rw(padap, MEMWIN_NIC, mem_type, bytes_read, + bytes, (__be32 *)(scratch_buff.data), 1); + + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_memory_rw failed (%d)", + __func__, rc); + cudbg_err->sys_err = rc; + goto err1; + } + +skip_read: + rc = compress_buff(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + bytes_left -= bytes; + bytes_read += bytes; + release_scratch_buff(&scratch_buff, dbg_buff); + } + +err1: + if (rc) + release_scratch_buff(&scratch_buff, dbg_buff); + +err: + return rc; +#endif + return (EDOOFUS); +} + +static void collect_mem_info(struct cudbg_init *pdbg_init, + struct card_mem *mem_info) +{ + struct adapter *padap = pdbg_init->adap; + u32 value; + int t4 = 0; + + if (is_t4(padap)) + t4 = 1; + + if (t4) { + value = t4_read_reg(padap, A_MA_EXT_MEMORY_BAR); + value = G_EXT_MEM_SIZE(value); + mem_info->size_mc0 = (u16)value; /* size in MB */ + + value = t4_read_reg(padap, A_MA_TARGET_MEM_ENABLE); + if (value & F_EXT_MEM_ENABLE) + mem_info->mem_flag |= (1 << MC0_FLAG); /* set mc0 flag + bit */ + } else { + value = t4_read_reg(padap, A_MA_EXT_MEMORY0_BAR); + value = G_EXT_MEM0_SIZE(value); + mem_info->size_mc0 = (u16)value; + + value = t4_read_reg(padap, A_MA_EXT_MEMORY1_BAR); + value = G_EXT_MEM1_SIZE(value); + mem_info->size_mc1 = (u16)value; + + value = t4_read_reg(padap, A_MA_TARGET_MEM_ENABLE); + if (value & F_EXT_MEM0_ENABLE) + mem_info->mem_flag |= (1 << MC0_FLAG); + if (value & F_EXT_MEM1_ENABLE) + mem_info->mem_flag |= (1 << MC1_FLAG); + } + + value = t4_read_reg(padap, A_MA_EDRAM0_BAR); + value = G_EDRAM0_SIZE(value); + mem_info->size_edc0 = (u16)value; + + value = t4_read_reg(padap, A_MA_EDRAM1_BAR); + value = G_EDRAM1_SIZE(value); + mem_info->size_edc1 = (u16)value; + + value = t4_read_reg(padap, A_MA_TARGET_MEM_ENABLE); + if (value & F_EDRAM0_ENABLE) + mem_info->mem_flag |= (1 << EDC0_FLAG); + if (value & F_EDRAM1_ENABLE) + mem_info->mem_flag |= (1 << EDC1_FLAG); + +} + +static void cudbg_t4_fwcache(struct cudbg_init *pdbg_init, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + int rc; + + if (is_fw_attached(pdbg_init)) { + + /* Flush uP dcache before reading edcX/mcX */ + rc = t4_fwcache(padap, FW_PARAM_DEV_FWCACHE_FLUSH); + + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("%s: t4_fwcache failed (%d)\n", + __func__, rc); + cudbg_err->sys_warn = rc; + } + } +} + +static int collect_edc0_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct card_mem mem_info = {0}; + unsigned long edc0_size; + int rc; + + cudbg_t4_fwcache(pdbg_init, cudbg_err); + + collect_mem_info(pdbg_init, &mem_info); + + if (mem_info.mem_flag & (1 << EDC0_FLAG)) { + edc0_size = (((unsigned long)mem_info.size_edc0) * 1024 * 1024); + rc = read_fw_mem(pdbg_init, dbg_buff, MEM_EDC0, + edc0_size, cudbg_err); + if (rc) + goto err; + + } else { + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + if (pdbg_init->verbose) + pdbg_init->print("%s(), collect_mem_info failed!, %s\n", + __func__, err_msg[-rc]); + goto err; + + } +err: + return rc; +} + +static int collect_edc1_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct card_mem mem_info = {0}; + unsigned long edc1_size; + int rc; + + cudbg_t4_fwcache(pdbg_init, cudbg_err); + + collect_mem_info(pdbg_init, &mem_info); + + if (mem_info.mem_flag & (1 << EDC1_FLAG)) { + edc1_size = (((unsigned long)mem_info.size_edc1) * 1024 * 1024); + rc = read_fw_mem(pdbg_init, dbg_buff, MEM_EDC1, + edc1_size, cudbg_err); + if (rc) + goto err; + } else { + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + if (pdbg_init->verbose) + pdbg_init->print("%s(), collect_mem_info failed!, %s\n", + __func__, err_msg[-rc]); + goto err; + } + +err: + + return rc; +} + +static int collect_mc0_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct card_mem mem_info = {0}; + unsigned long mc0_size; + int rc; + + cudbg_t4_fwcache(pdbg_init, cudbg_err); + + collect_mem_info(pdbg_init, &mem_info); + + if (mem_info.mem_flag & (1 << MC0_FLAG)) { + mc0_size = (((unsigned long)mem_info.size_mc0) * 1024 * 1024); + rc = read_fw_mem(pdbg_init, dbg_buff, MEM_MC0, + mc0_size, cudbg_err); + if (rc) + goto err; + } else { + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + if (pdbg_init->verbose) + pdbg_init->print("%s(), collect_mem_info failed!, %s\n", + __func__, err_msg[-rc]); + goto err; + } + +err: + return rc; +} + +static int collect_mc1_meminfo(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct card_mem mem_info = {0}; + unsigned long mc1_size; + int rc; + + cudbg_t4_fwcache(pdbg_init, cudbg_err); + + collect_mem_info(pdbg_init, &mem_info); + + if (mem_info.mem_flag & (1 << MC1_FLAG)) { + mc1_size = (((unsigned long)mem_info.size_mc1) * 1024 * 1024); + rc = read_fw_mem(pdbg_init, dbg_buff, MEM_MC1, + mc1_size, cudbg_err); + if (rc) + goto err; + } else { + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + + if (pdbg_init->verbose) + pdbg_init->print("%s(), collect_mem_info failed!, %s\n", + __func__, err_msg[-rc]); + goto err; + } +err: + return rc; +} + +static int collect_reg_dump(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct cudbg_buffer tmp_scratch_buff; + struct adapter *padap = pdbg_init->adap; + unsigned long bytes_read = 0; + unsigned long bytes_left; + u32 buf_size = 0, bytes = 0; + int rc = 0; + + if (is_t4(padap)) + buf_size = T4_REGMAP_SIZE ;/*+ sizeof(unsigned int);*/ + else if (is_t5(padap) || is_t6(padap)) + buf_size = T5_REGMAP_SIZE; + + scratch_buff.size = buf_size; + + tmp_scratch_buff = scratch_buff; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + /* no return */ + t4_get_regs(padap, (void *)scratch_buff.data, scratch_buff.size); + bytes_left = scratch_buff.size; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + while (bytes_left > 0) { + tmp_scratch_buff.data = + ((char *)scratch_buff.data) + bytes_read; + bytes = min_t(unsigned long, bytes_left, (unsigned long)CUDBG_CHUNK_SIZE); + tmp_scratch_buff.size = bytes; + compress_buff(&tmp_scratch_buff, dbg_buff); + bytes_left -= bytes; + bytes_read += bytes; + } + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_cctrl(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 size; + int rc; + + size = sizeof(u16) * NMTUS * NCCTRL_WIN; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + t4_read_cong_tbl(padap, (void *)scratch_buff.data); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int check_busy_bit(struct adapter *padap) +{ + u32 val; + u32 busy = 1; + int i = 0; + int retry = 10; + int status = 0; + + while (busy & (1 < retry)) { + val = t4_read_reg(padap, A_CIM_HOST_ACC_CTRL); + busy = (0 != (val & CUDBG_CIM_BUSY_BIT)); + i++; + } + + if (busy) + status = -1; + + return status; +} + +static int cim_ha_rreg(struct adapter *padap, u32 addr, u32 *val) +{ + int rc = 0; + + /* write register address into the A_CIM_HOST_ACC_CTRL */ + t4_write_reg(padap, A_CIM_HOST_ACC_CTRL, addr); + + /* Poll HOSTBUSY */ + rc = check_busy_bit(padap); + if (rc) + goto err; + + /* Read value from A_CIM_HOST_ACC_DATA */ + *val = t4_read_reg(padap, A_CIM_HOST_ACC_DATA); + +err: + return rc; +} + +static int dump_up_cim(struct adapter *padap, struct cudbg_init *pdbg_init, + struct ireg_field *up_cim_reg, u32 *buff) +{ + u32 i; + int rc = 0; + + for (i = 0; i < up_cim_reg->ireg_offset_range; i++) { + rc = cim_ha_rreg(padap, + up_cim_reg->ireg_local_offset + (i * 4), + buff); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("BUSY timeout reading" + "CIM_HOST_ACC_CTRL\n"); + goto err; + } + + buff++; + } + +err: + return rc; +} + +static int collect_up_cim_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *up_cim; + u32 size; + int i, rc, n; + + n = sizeof(t5_up_cim_reg_array) / (4 * sizeof(u32)); + size = sizeof(struct ireg_buf) * n; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + up_cim = (struct ireg_buf *)scratch_buff.data; + + for (i = 0; i < n; i++) { + struct ireg_field *up_cim_reg = &up_cim->tp_pio; + u32 *buff = up_cim->outbuf; + + if (is_t5(padap)) { + up_cim_reg->ireg_addr = t5_up_cim_reg_array[i][0]; + up_cim_reg->ireg_data = t5_up_cim_reg_array[i][1]; + up_cim_reg->ireg_local_offset = + t5_up_cim_reg_array[i][2]; + up_cim_reg->ireg_offset_range = + t5_up_cim_reg_array[i][3]; + } else if (is_t6(padap)) { + up_cim_reg->ireg_addr = t6_up_cim_reg_array[i][0]; + up_cim_reg->ireg_data = t6_up_cim_reg_array[i][1]; + up_cim_reg->ireg_local_offset = + t6_up_cim_reg_array[i][2]; + up_cim_reg->ireg_offset_range = + t6_up_cim_reg_array[i][3]; + } + + rc = dump_up_cim(padap, pdbg_init, up_cim_reg, buff); + + up_cim++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_mbox_log(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ +#ifdef notyet + struct cudbg_buffer scratch_buff; + struct cudbg_mbox_log *mboxlog = NULL; + struct mbox_cmd_log *log = NULL; + struct mbox_cmd *entry; + u64 flit; + u32 size; + unsigned int entry_idx; + int i, k, rc; + u16 mbox_cmds; + + if (pdbg_init->dbg_params[CUDBG_MBOX_LOG_PARAM].u.mboxlog_param.log) { + log = pdbg_init->dbg_params[CUDBG_MBOX_LOG_PARAM].u. + mboxlog_param.log; + mbox_cmds = pdbg_init->dbg_params[CUDBG_MBOX_LOG_PARAM].u. + mboxlog_param.mbox_cmds; + } else { + if (pdbg_init->verbose) + pdbg_init->print("Mbox log is not requested\n"); + return CUDBG_STATUS_ENTITY_NOT_REQUESTED; + } + + size = sizeof(struct cudbg_mbox_log) * mbox_cmds; + scratch_buff.size = size; + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + mboxlog = (struct cudbg_mbox_log *)scratch_buff.data; + + for (k = 0; k < mbox_cmds; k++) { + entry_idx = log->cursor + k; + if (entry_idx >= log->size) + entry_idx -= log->size; + entry = mbox_cmd_log_entry(log, entry_idx); + + /* skip over unused entries */ + if (entry->timestamp == 0) + continue; + + memcpy(&mboxlog->entry, entry, sizeof(struct mbox_cmd)); + + for (i = 0; i < MBOX_LEN / 8; i++) { + flit = entry->cmd[i]; + mboxlog->hi[i] = (u32)(flit >> 32); + mboxlog->lo[i] = (u32)flit; + } + + mboxlog++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +#endif + return (EDOOFUS); +} + +static int collect_pbt_tables(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct cudbg_pbt_tables *pbt = NULL; + u32 size; + u32 addr; + int i, rc; + + size = sizeof(struct cudbg_pbt_tables); + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + pbt = (struct cudbg_pbt_tables *)scratch_buff.data; + + /* PBT dynamic entries */ + addr = CUDBG_CHAC_PBT_ADDR; + for (i = 0; i < CUDBG_PBT_DYNAMIC_ENTRIES; i++) { + rc = cim_ha_rreg(padap, addr + (i * 4), &pbt->pbt_dynamic[i]); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("BUSY timeout reading" + "CIM_HOST_ACC_CTRL\n"); + goto err1; + } + } + + /* PBT static entries */ + + /* static entries start when bit 6 is set */ + addr = CUDBG_CHAC_PBT_ADDR + (1 << 6); + for (i = 0; i < CUDBG_PBT_STATIC_ENTRIES; i++) { + rc = cim_ha_rreg(padap, addr + (i * 4), &pbt->pbt_static[i]); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("BUSY timeout reading" + "CIM_HOST_ACC_CTRL\n"); + goto err1; + } + } + + /* LRF entries */ + addr = CUDBG_CHAC_PBT_LRF; + for (i = 0; i < CUDBG_LRF_ENTRIES; i++) { + rc = cim_ha_rreg(padap, addr + (i * 4), &pbt->lrf_table[i]); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("BUSY timeout reading" + "CIM_HOST_ACC_CTRL\n"); + goto err1; + } + } + + /* PBT data entries */ + addr = CUDBG_CHAC_PBT_DATA; + for (i = 0; i < CUDBG_PBT_DATA_ENTRIES; i++) { + rc = cim_ha_rreg(padap, addr + (i * 4), &pbt->pbt_data[i]); + if (rc) { + if (pdbg_init->verbose) + pdbg_init->print("BUSY timeout reading" + "CIM_HOST_ACC_CTRL\n"); + goto err1; + } + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_pm_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *ch_pm; + u32 size; + int i, rc, n; + + n = sizeof(t5_pm_rx_array) / (4 * sizeof(u32)); + size = sizeof(struct ireg_buf) * n * 2; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + ch_pm = (struct ireg_buf *)scratch_buff.data; + + /*PM_RX*/ + for (i = 0; i < n; i++) { + struct ireg_field *pm_pio = &ch_pm->tp_pio; + u32 *buff = ch_pm->outbuf; + + pm_pio->ireg_addr = t5_pm_rx_array[i][0]; + pm_pio->ireg_data = t5_pm_rx_array[i][1]; + pm_pio->ireg_local_offset = t5_pm_rx_array[i][2]; + pm_pio->ireg_offset_range = t5_pm_rx_array[i][3]; + + t4_read_indirect(padap, + pm_pio->ireg_addr, + pm_pio->ireg_data, + buff, + pm_pio->ireg_offset_range, + pm_pio->ireg_local_offset); + + ch_pm++; + } + + /*PM_Tx*/ + n = sizeof(t5_pm_tx_array) / (4 * sizeof(u32)); + for (i = 0; i < n; i++) { + struct ireg_field *pm_pio = &ch_pm->tp_pio; + u32 *buff = ch_pm->outbuf; + + pm_pio->ireg_addr = t5_pm_tx_array[i][0]; + pm_pio->ireg_data = t5_pm_tx_array[i][1]; + pm_pio->ireg_local_offset = t5_pm_tx_array[i][2]; + pm_pio->ireg_offset_range = t5_pm_tx_array[i][3]; + + t4_read_indirect(padap, + pm_pio->ireg_addr, + pm_pio->ireg_data, + buff, + pm_pio->ireg_offset_range, + pm_pio->ireg_local_offset); + + ch_pm++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; + +} + +static int collect_tid(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct tid_info_region *tid; + struct tid_info_region_rev1 *tid1; + u32 para[7], val[7]; + u32 mbox, pf; + int rc; + + scratch_buff.size = sizeof(struct tid_info_region_rev1); + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + +#define FW_PARAM_DEV_A(param) \ + (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ + V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) +#define FW_PARAM_PFVF_A(param) \ + (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ + V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)| \ + V_FW_PARAMS_PARAM_Y(0) | \ + V_FW_PARAMS_PARAM_Z(0)) +#define MAX_ATIDS_A 8192U + + tid1 = (struct tid_info_region_rev1 *)scratch_buff.data; + tid = &(tid1->tid); + tid1->ver_hdr.signature = CUDBG_ENTITY_SIGNATURE; + tid1->ver_hdr.revision = CUDBG_TID_INFO_REV; + tid1->ver_hdr.size = sizeof(struct tid_info_region_rev1) - + sizeof(struct cudbg_ver_hdr); + + if (is_t5(padap)) { + tid->hash_base = t4_read_reg(padap, A_LE_DB_TID_HASHBASE); + tid1->tid_start = 0; + } else if (is_t6(padap)) { + tid->hash_base = t4_read_reg(padap, A_T6_LE_DB_HASH_TID_BASE); + tid1->tid_start = t4_read_reg(padap, A_LE_DB_ACTIVE_TABLE_START_INDEX); + } + + tid->le_db_conf = t4_read_reg(padap, A_LE_DB_CONFIG); + + para[0] = FW_PARAM_PFVF_A(FILTER_START); + para[1] = FW_PARAM_PFVF_A(FILTER_END); + para[2] = FW_PARAM_PFVF_A(ACTIVE_FILTER_START); + para[3] = FW_PARAM_PFVF_A(ACTIVE_FILTER_END); + para[4] = FW_PARAM_DEV_A(NTID); + para[5] = FW_PARAM_PFVF_A(SERVER_START); + para[6] = FW_PARAM_PFVF_A(SERVER_END); + + mbox = padap->mbox; + pf = padap->pf; + rc = t4_query_params(padap, mbox, pf, 0, 7, para, val); + if (rc < 0) { + if (rc == -FW_EPERM) { + /* It looks like we don't have permission to use + * padap->mbox. + * + * Try mbox 4. If it works, we'll continue to + * collect the rest of tid info from mbox 4. + * Else, quit trying to collect tid info. + */ + mbox = 4; + pf = 4; + rc = t4_query_params(padap, mbox, pf, 0, 7, para, val); + if (rc < 0) { + cudbg_err->sys_err = rc; + goto err1; + } + } else { + cudbg_err->sys_err = rc; + goto err1; + } + } + + tid->ftid_base = val[0]; + tid->nftids = val[1] - val[0] + 1; + /*active filter region*/ + if (val[2] != val[3]) { +#ifdef notyet + tid->flags |= FW_OFLD_CONN; +#endif + tid->aftid_base = val[2]; + tid->aftid_end = val[3]; + } + tid->ntids = val[4]; + tid->natids = min_t(u32, tid->ntids / 2, MAX_ATIDS_A); + tid->stid_base = val[5]; + tid->nstids = val[6] - val[5] + 1; + + if (chip_id(padap) >= CHELSIO_T6) { + para[0] = FW_PARAM_PFVF_A(HPFILTER_START); + para[1] = FW_PARAM_PFVF_A(HPFILTER_END); + rc = t4_query_params(padap, mbox, pf, 0, 2, para, val); + if (rc < 0) { + cudbg_err->sys_err = rc; + goto err1; + } + + tid->hpftid_base = val[0]; + tid->nhpftids = val[1] - val[0] + 1; + } + + if (chip_id(padap) <= CHELSIO_T5) { + tid->sb = t4_read_reg(padap, A_LE_DB_SERVER_INDEX) / 4; + tid->hash_base /= 4; + } else + tid->sb = t4_read_reg(padap, A_LE_DB_SRVR_START_INDEX); + + /*UO context range*/ + para[0] = FW_PARAM_PFVF_A(ETHOFLD_START); + para[1] = FW_PARAM_PFVF_A(ETHOFLD_END); + + rc = t4_query_params(padap, mbox, pf, 0, 2, para, val); + if (rc < 0) { + cudbg_err->sys_err = rc; + goto err1; + } + + if (val[0] != val[1]) { + tid->uotid_base = val[0]; + tid->nuotids = val[1] - val[0] + 1; + } + tid->IP_users = t4_read_reg(padap, A_LE_DB_ACT_CNT_IPV4); + tid->IPv6_users = t4_read_reg(padap, A_LE_DB_ACT_CNT_IPV6); + +#undef FW_PARAM_PFVF_A +#undef FW_PARAM_DEV_A +#undef MAX_ATIDS_A + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_tx_rate(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct tx_rate *tx_rate; + u32 size; + int rc; + + size = sizeof(struct tx_rate); + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + tx_rate = (struct tx_rate *)scratch_buff.data; + t4_get_chan_txrate(padap, tx_rate->nrate, tx_rate->orate); + tx_rate->nchan = padap->chip_params->nchan; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static inline void cudbg_tcamxy2valmask(u64 x, u64 y, u8 *addr, u64 *mask) +{ + *mask = x | y; + y = (__force u64)cpu_to_be64(y); + memcpy(addr, (char *)&y + 2, ETH_ALEN); +} + +static void mps_rpl_backdoor(struct adapter *padap, struct fw_ldst_mps_rplc *mps_rplc) +{ + if (is_t5(padap)) { + mps_rplc->rplc255_224 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP3)); + mps_rplc->rplc223_192 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP2)); + mps_rplc->rplc191_160 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP1)); + mps_rplc->rplc159_128 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP0)); + } else { + mps_rplc->rplc255_224 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP7)); + mps_rplc->rplc223_192 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP6)); + mps_rplc->rplc191_160 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP5)); + mps_rplc->rplc159_128 = htonl(t4_read_reg(padap, + A_MPS_VF_RPLCT_MAP4)); + } + mps_rplc->rplc127_96 = htonl(t4_read_reg(padap, A_MPS_VF_RPLCT_MAP3)); + mps_rplc->rplc95_64 = htonl(t4_read_reg(padap, A_MPS_VF_RPLCT_MAP2)); + mps_rplc->rplc63_32 = htonl(t4_read_reg(padap, A_MPS_VF_RPLCT_MAP1)); + mps_rplc->rplc31_0 = htonl(t4_read_reg(padap, A_MPS_VF_RPLCT_MAP0)); +} + +static int collect_mps_tcam(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct cudbg_mps_tcam *tcam = NULL; + u32 size = 0, i, n, total_size = 0; + u32 ctl, data2; + u64 tcamy, tcamx, val; + int rc; + + n = padap->chip_params->mps_tcam_size; + size = sizeof(struct cudbg_mps_tcam) * n; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + memset(scratch_buff.data, 0, size); + + tcam = (struct cudbg_mps_tcam *)scratch_buff.data; + for (i = 0; i < n; i++) { + if (chip_id(padap) >= CHELSIO_T6) { + /* CtlReqID - 1: use Host Driver Requester ID + * CtlCmdType - 0: Read, 1: Write + * CtlTcamSel - 0: TCAM0, 1: TCAM1 + * CtlXYBitSel- 0: Y bit, 1: X bit + */ + + /* Read tcamy */ + ctl = (V_CTLREQID(1) | + V_CTLCMDTYPE(0) | V_CTLXYBITSEL(0)); + if (i < 256) + ctl |= V_CTLTCAMINDEX(i) | V_CTLTCAMSEL(0); + else + ctl |= V_CTLTCAMINDEX(i - 256) | + V_CTLTCAMSEL(1); + + t4_write_reg(padap, A_MPS_CLS_TCAM_DATA2_CTL, ctl); + val = t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA1_REQ_ID1); + tcamy = G_DMACH(val) << 32; + tcamy |= t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA0_REQ_ID1); + data2 = t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA2_REQ_ID1); + tcam->lookup_type = G_DATALKPTYPE(data2); + + /* 0 - Outer header, 1 - Inner header + * [71:48] bit locations are overloaded for + * outer vs. inner lookup types. + */ + + if (tcam->lookup_type && + (tcam->lookup_type != M_DATALKPTYPE)) { + /* Inner header VNI */ + tcam->vniy = ((data2 & F_DATAVIDH2) << 23) | + (G_DATAVIDH1(data2) << 16) | + G_VIDL(val); + tcam->dip_hit = data2 & F_DATADIPHIT; + } else { + tcam->vlan_vld = data2 & F_DATAVIDH2; + tcam->ivlan = G_VIDL(val); + } + + tcam->port_num = G_DATAPORTNUM(data2); + + /* Read tcamx. Change the control param */ + ctl |= V_CTLXYBITSEL(1); + t4_write_reg(padap, A_MPS_CLS_TCAM_DATA2_CTL, ctl); + val = t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA1_REQ_ID1); + tcamx = G_DMACH(val) << 32; + tcamx |= t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA0_REQ_ID1); + data2 = t4_read_reg(padap, A_MPS_CLS_TCAM_RDATA2_REQ_ID1); + if (tcam->lookup_type && + (tcam->lookup_type != M_DATALKPTYPE)) { + /* Inner header VNI mask */ + tcam->vnix = ((data2 & F_DATAVIDH2) << 23) | + (G_DATAVIDH1(data2) << 16) | + G_VIDL(val); + } + } else { + tcamy = t4_read_reg64(padap, MPS_CLS_TCAM_Y_L(i)); + tcamx = t4_read_reg64(padap, MPS_CLS_TCAM_X_L(i)); + } + + if (tcamx & tcamy) + continue; + + tcam->cls_lo = t4_read_reg(padap, MPS_CLS_SRAM_L(i)); + tcam->cls_hi = t4_read_reg(padap, MPS_CLS_SRAM_H(i)); + + if (is_t5(padap)) + tcam->repli = (tcam->cls_lo & F_REPLICATE); + else if (is_t6(padap)) + tcam->repli = (tcam->cls_lo & F_T6_REPLICATE); + + if (tcam->repli) { + struct fw_ldst_cmd ldst_cmd; + struct fw_ldst_mps_rplc mps_rplc; + + memset(&ldst_cmd, 0, sizeof(ldst_cmd)); + ldst_cmd.op_to_addrspace = + htonl(V_FW_CMD_OP(FW_LDST_CMD) | + F_FW_CMD_REQUEST | + F_FW_CMD_READ | + V_FW_LDST_CMD_ADDRSPACE( + FW_LDST_ADDRSPC_MPS)); + + ldst_cmd.cycles_to_len16 = htonl(FW_LEN16(ldst_cmd)); + + ldst_cmd.u.mps.rplc.fid_idx = + htons(V_FW_LDST_CMD_FID(FW_LDST_MPS_RPLC) | + V_FW_LDST_CMD_IDX(i)); + + rc = t4_wr_mbox(padap, padap->mbox, &ldst_cmd, + sizeof(ldst_cmd), &ldst_cmd); + + if (rc) + mps_rpl_backdoor(padap, &mps_rplc); + else + mps_rplc = ldst_cmd.u.mps.rplc; + + tcam->rplc[0] = ntohl(mps_rplc.rplc31_0); + tcam->rplc[1] = ntohl(mps_rplc.rplc63_32); + tcam->rplc[2] = ntohl(mps_rplc.rplc95_64); + tcam->rplc[3] = ntohl(mps_rplc.rplc127_96); + if (padap->chip_params->mps_rplc_size > + CUDBG_MAX_RPLC_SIZE) { + tcam->rplc[4] = ntohl(mps_rplc.rplc159_128); + tcam->rplc[5] = ntohl(mps_rplc.rplc191_160); + tcam->rplc[6] = ntohl(mps_rplc.rplc223_192); + tcam->rplc[7] = ntohl(mps_rplc.rplc255_224); + } + } + cudbg_tcamxy2valmask(tcamx, tcamy, tcam->addr, &tcam->mask); + + tcam->idx = i; + tcam->rplc_size = padap->chip_params->mps_rplc_size; + + total_size += sizeof(struct cudbg_mps_tcam); + + tcam++; + } + + if (total_size == 0) { + rc = CUDBG_SYSTEM_ERROR; + goto err1; + } + + scratch_buff.size = total_size; + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + scratch_buff.size = size; + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_pcie_config(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 size, *value, j; + int i, rc, n; + + size = sizeof(u32) * NUM_PCIE_CONFIG_REGS; + n = sizeof(t5_pcie_config_array) / (2 * sizeof(u32)); + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + value = (u32 *)scratch_buff.data; + for (i = 0; i < n; i++) { + for (j = t5_pcie_config_array[i][0]; + j <= t5_pcie_config_array[i][1]; j += 4) { + *value++ = t4_hw_pci_read_cfg4(padap, j); + } + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int cudbg_read_tid(struct cudbg_init *pdbg_init, u32 tid, + struct cudbg_tid_data *tid_data) +{ + int i, cmd_retry = 8; + struct adapter *padap = pdbg_init->adap; + u32 val; + + /* Fill REQ_DATA regs with 0's */ + for (i = 0; i < CUDBG_NUM_REQ_REGS; i++) + t4_write_reg(padap, A_LE_DB_DBGI_REQ_DATA + (i << 2), 0); + + /* Write DBIG command */ + val = (0x4 << S_DBGICMD) | tid; + t4_write_reg(padap, A_LE_DB_DBGI_REQ_TCAM_CMD, val); + tid_data->dbig_cmd = val; + + val = 0; + val |= 1 << S_DBGICMDSTRT; + val |= 1; /* LE mode */ + t4_write_reg(padap, A_LE_DB_DBGI_CONFIG, val); + tid_data->dbig_conf = val; + + /* Poll the DBGICMDBUSY bit */ + val = 1; + while (val) { + val = t4_read_reg(padap, A_LE_DB_DBGI_CONFIG); + val = (val >> S_DBGICMDBUSY) & 1; + cmd_retry--; + if (!cmd_retry) { + if (pdbg_init->verbose) + pdbg_init->print("%s(): Timeout waiting for non-busy\n", + __func__); + return CUDBG_SYSTEM_ERROR; + } + } + + /* Check RESP status */ + val = 0; + val = t4_read_reg(padap, A_LE_DB_DBGI_RSP_STATUS); + tid_data->dbig_rsp_stat = val; + if (!(val & 1)) { + if (pdbg_init->verbose) + pdbg_init->print("%s(): DBGI command failed\n", __func__); + return CUDBG_SYSTEM_ERROR; + } + + /* Read RESP data */ + for (i = 0; i < CUDBG_NUM_REQ_REGS; i++) + tid_data->data[i] = t4_read_reg(padap, + A_LE_DB_DBGI_RSP_DATA + + (i << 2)); + + tid_data->tid = tid; + + return 0; +} + +static int collect_le_tcam(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct cudbg_tcam tcam_region = {0}; + struct cudbg_tid_data *tid_data = NULL; + u32 value, bytes = 0, bytes_left = 0; + u32 i; + int rc, size; + + /* Get the LE regions */ + value = t4_read_reg(padap, A_LE_DB_TID_HASHBASE); /* Get hash base + index */ + tcam_region.tid_hash_base = value; + + /* Get routing table index */ + value = t4_read_reg(padap, A_LE_DB_ROUTING_TABLE_INDEX); + tcam_region.routing_start = value; + + /*Get clip table index */ + value = t4_read_reg(padap, A_LE_DB_CLIP_TABLE_INDEX); + tcam_region.clip_start = value; + + /* Get filter table index */ + value = t4_read_reg(padap, A_LE_DB_FILTER_TABLE_INDEX); + tcam_region.filter_start = value; + + /* Get server table index */ + value = t4_read_reg(padap, A_LE_DB_SERVER_INDEX); + tcam_region.server_start = value; + + /* Check whether hash is enabled and calculate the max tids */ + value = t4_read_reg(padap, A_LE_DB_CONFIG); + if ((value >> S_HASHEN) & 1) { + value = t4_read_reg(padap, A_LE_DB_HASH_CONFIG); + if (chip_id(padap) > CHELSIO_T5) + tcam_region.max_tid = (value & 0xFFFFF) + + tcam_region.tid_hash_base; + else { /* for T5 */ + value = G_HASHTIDSIZE(value); + value = 1 << value; + tcam_region.max_tid = value + + tcam_region.tid_hash_base; + } + } else /* hash not enabled */ + tcam_region.max_tid = CUDBG_MAX_TCAM_TID; + + size = sizeof(struct cudbg_tid_data) * tcam_region.max_tid; + size += sizeof(struct cudbg_tcam); + scratch_buff.size = size; + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err; + + rc = get_scratch_buff(dbg_buff, CUDBG_CHUNK_SIZE, &scratch_buff); + if (rc) + goto err; + + memcpy(scratch_buff.data, &tcam_region, sizeof(struct cudbg_tcam)); + + tid_data = (struct cudbg_tid_data *)(((struct cudbg_tcam *) + scratch_buff.data) + 1); + bytes_left = CUDBG_CHUNK_SIZE - sizeof(struct cudbg_tcam); + bytes = sizeof(struct cudbg_tcam); + + /* read all tid */ + for (i = 0; i < tcam_region.max_tid; i++) { + if (bytes_left < sizeof(struct cudbg_tid_data)) { + scratch_buff.size = bytes; + rc = compress_buff(&scratch_buff, dbg_buff); + if (rc) + goto err1; + scratch_buff.size = CUDBG_CHUNK_SIZE; + release_scratch_buff(&scratch_buff, dbg_buff); + + /* new alloc */ + rc = get_scratch_buff(dbg_buff, CUDBG_CHUNK_SIZE, + &scratch_buff); + if (rc) + goto err; + + tid_data = (struct cudbg_tid_data *)(scratch_buff.data); + bytes_left = CUDBG_CHUNK_SIZE; + bytes = 0; + } + + rc = cudbg_read_tid(pdbg_init, i, tid_data); + + if (rc) { + cudbg_err->sys_err = rc; + goto err1; + } + + tid_data++; + bytes_left -= sizeof(struct cudbg_tid_data); + bytes += sizeof(struct cudbg_tid_data); + } + + if (bytes) { + scratch_buff.size = bytes; + rc = compress_buff(&scratch_buff, dbg_buff); + } + +err1: + scratch_buff.size = CUDBG_CHUNK_SIZE; + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_ma_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *ma_indr = NULL; + u32 size, j; + int i, rc, n; + + if (chip_id(padap) < CHELSIO_T6) { + if (pdbg_init->verbose) + pdbg_init->print("MA indirect available only in T6\n"); + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + goto err; + } + + n = sizeof(t6_ma_ireg_array) / (4 * sizeof(u32)); + size = sizeof(struct ireg_buf) * n * 2; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + ma_indr = (struct ireg_buf *)scratch_buff.data; + + for (i = 0; i < n; i++) { + struct ireg_field *ma_fli = &ma_indr->tp_pio; + u32 *buff = ma_indr->outbuf; + + ma_fli->ireg_addr = t6_ma_ireg_array[i][0]; + ma_fli->ireg_data = t6_ma_ireg_array[i][1]; + ma_fli->ireg_local_offset = t6_ma_ireg_array[i][2]; + ma_fli->ireg_offset_range = t6_ma_ireg_array[i][3]; + + t4_read_indirect(padap, ma_fli->ireg_addr, ma_fli->ireg_data, + buff, ma_fli->ireg_offset_range, + ma_fli->ireg_local_offset); + + ma_indr++; + + } + + n = sizeof(t6_ma_ireg_array2) / (4 * sizeof(u32)); + + for (i = 0; i < n; i++) { + struct ireg_field *ma_fli = &ma_indr->tp_pio; + u32 *buff = ma_indr->outbuf; + + ma_fli->ireg_addr = t6_ma_ireg_array2[i][0]; + ma_fli->ireg_data = t6_ma_ireg_array2[i][1]; + ma_fli->ireg_local_offset = t6_ma_ireg_array2[i][2]; + + for (j = 0; j < t6_ma_ireg_array2[i][3]; j++) { + t4_read_indirect(padap, ma_fli->ireg_addr, + ma_fli->ireg_data, buff, 1, + ma_fli->ireg_local_offset); + buff++; + ma_fli->ireg_local_offset += 0x20; + } + ma_indr++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_hma_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *hma_indr = NULL; + u32 size; + int i, rc, n; + + if (chip_id(padap) < CHELSIO_T6) { + if (pdbg_init->verbose) + pdbg_init->print("HMA indirect available only in T6\n"); + rc = CUDBG_STATUS_ENTITY_NOT_FOUND; + goto err; + } + + n = sizeof(t6_hma_ireg_array) / (4 * sizeof(u32)); + size = sizeof(struct ireg_buf) * n; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + hma_indr = (struct ireg_buf *)scratch_buff.data; + + for (i = 0; i < n; i++) { + struct ireg_field *hma_fli = &hma_indr->tp_pio; + u32 *buff = hma_indr->outbuf; + + hma_fli->ireg_addr = t6_hma_ireg_array[i][0]; + hma_fli->ireg_data = t6_hma_ireg_array[i][1]; + hma_fli->ireg_local_offset = t6_hma_ireg_array[i][2]; + hma_fli->ireg_offset_range = t6_hma_ireg_array[i][3]; + + t4_read_indirect(padap, hma_fli->ireg_addr, hma_fli->ireg_data, + buff, hma_fli->ireg_offset_range, + hma_fli->ireg_local_offset); + + hma_indr++; + + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_pcie_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *ch_pcie; + u32 size; + int i, rc, n; + + n = sizeof(t5_pcie_pdbg_array) / (4 * sizeof(u32)); + size = sizeof(struct ireg_buf) * n * 2; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + ch_pcie = (struct ireg_buf *)scratch_buff.data; + + /*PCIE_PDBG*/ + for (i = 0; i < n; i++) { + struct ireg_field *pcie_pio = &ch_pcie->tp_pio; + u32 *buff = ch_pcie->outbuf; + + pcie_pio->ireg_addr = t5_pcie_pdbg_array[i][0]; + pcie_pio->ireg_data = t5_pcie_pdbg_array[i][1]; + pcie_pio->ireg_local_offset = t5_pcie_pdbg_array[i][2]; + pcie_pio->ireg_offset_range = t5_pcie_pdbg_array[i][3]; + + t4_read_indirect(padap, + pcie_pio->ireg_addr, + pcie_pio->ireg_data, + buff, + pcie_pio->ireg_offset_range, + pcie_pio->ireg_local_offset); + + ch_pcie++; + } + + /*PCIE_CDBG*/ + n = sizeof(t5_pcie_cdbg_array) / (4 * sizeof(u32)); + for (i = 0; i < n; i++) { + struct ireg_field *pcie_pio = &ch_pcie->tp_pio; + u32 *buff = ch_pcie->outbuf; + + pcie_pio->ireg_addr = t5_pcie_cdbg_array[i][0]; + pcie_pio->ireg_data = t5_pcie_cdbg_array[i][1]; + pcie_pio->ireg_local_offset = t5_pcie_cdbg_array[i][2]; + pcie_pio->ireg_offset_range = t5_pcie_cdbg_array[i][3]; + + t4_read_indirect(padap, + pcie_pio->ireg_addr, + pcie_pio->ireg_data, + buff, + pcie_pio->ireg_offset_range, + pcie_pio->ireg_local_offset); + + ch_pcie++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; + +} + +static int collect_tp_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *ch_tp_pio; + u32 size; + int i, rc, n = 0; + + if (is_t5(padap)) + n = sizeof(t5_tp_pio_array) / (4 * sizeof(u32)); + else if (is_t6(padap)) + n = sizeof(t6_tp_pio_array) / (4 * sizeof(u32)); + + size = sizeof(struct ireg_buf) * n * 3; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + ch_tp_pio = (struct ireg_buf *)scratch_buff.data; + + /* TP_PIO*/ + for (i = 0; i < n; i++) { + struct ireg_field *tp_pio = &ch_tp_pio->tp_pio; + u32 *buff = ch_tp_pio->outbuf; + + if (is_t5(padap)) { + tp_pio->ireg_addr = t5_tp_pio_array[i][0]; + tp_pio->ireg_data = t5_tp_pio_array[i][1]; + tp_pio->ireg_local_offset = t5_tp_pio_array[i][2]; + tp_pio->ireg_offset_range = t5_tp_pio_array[i][3]; + } else if (is_t6(padap)) { + tp_pio->ireg_addr = t6_tp_pio_array[i][0]; + tp_pio->ireg_data = t6_tp_pio_array[i][1]; + tp_pio->ireg_local_offset = t6_tp_pio_array[i][2]; + tp_pio->ireg_offset_range = t6_tp_pio_array[i][3]; + } + + t4_tp_pio_read(padap, buff, tp_pio->ireg_offset_range, + tp_pio->ireg_local_offset, true); + + ch_tp_pio++; + } + + /* TP_TM_PIO*/ + if (is_t5(padap)) + n = sizeof(t5_tp_tm_pio_array) / (4 * sizeof(u32)); + else if (is_t6(padap)) + n = sizeof(t6_tp_tm_pio_array) / (4 * sizeof(u32)); + + for (i = 0; i < n; i++) { + struct ireg_field *tp_pio = &ch_tp_pio->tp_pio; + u32 *buff = ch_tp_pio->outbuf; + + if (is_t5(padap)) { + tp_pio->ireg_addr = t5_tp_tm_pio_array[i][0]; + tp_pio->ireg_data = t5_tp_tm_pio_array[i][1]; + tp_pio->ireg_local_offset = t5_tp_tm_pio_array[i][2]; + tp_pio->ireg_offset_range = t5_tp_tm_pio_array[i][3]; + } else if (is_t6(padap)) { + tp_pio->ireg_addr = t6_tp_tm_pio_array[i][0]; + tp_pio->ireg_data = t6_tp_tm_pio_array[i][1]; + tp_pio->ireg_local_offset = t6_tp_tm_pio_array[i][2]; + tp_pio->ireg_offset_range = t6_tp_tm_pio_array[i][3]; + } + + t4_tp_tm_pio_read(padap, buff, tp_pio->ireg_offset_range, + tp_pio->ireg_local_offset, true); + + ch_tp_pio++; + } + + /* TP_MIB_INDEX*/ + if (is_t5(padap)) + n = sizeof(t5_tp_mib_index_array) / (4 * sizeof(u32)); + else if (is_t6(padap)) + n = sizeof(t6_tp_mib_index_array) / (4 * sizeof(u32)); + + for (i = 0; i < n ; i++) { + struct ireg_field *tp_pio = &ch_tp_pio->tp_pio; + u32 *buff = ch_tp_pio->outbuf; + + if (is_t5(padap)) { + tp_pio->ireg_addr = t5_tp_mib_index_array[i][0]; + tp_pio->ireg_data = t5_tp_mib_index_array[i][1]; + tp_pio->ireg_local_offset = + t5_tp_mib_index_array[i][2]; + tp_pio->ireg_offset_range = + t5_tp_mib_index_array[i][3]; + } else if (is_t6(padap)) { + tp_pio->ireg_addr = t6_tp_mib_index_array[i][0]; + tp_pio->ireg_data = t6_tp_mib_index_array[i][1]; + tp_pio->ireg_local_offset = + t6_tp_mib_index_array[i][2]; + tp_pio->ireg_offset_range = + t6_tp_mib_index_array[i][3]; + } + + t4_tp_mib_read(padap, buff, tp_pio->ireg_offset_range, + tp_pio->ireg_local_offset, true); + + ch_tp_pio++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_sge_indirect(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct ireg_buf *ch_sge_dbg; + u32 size; + int i, rc; + + size = sizeof(struct ireg_buf) * 2; + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + ch_sge_dbg = (struct ireg_buf *)scratch_buff.data; + + for (i = 0; i < 2; i++) { + struct ireg_field *sge_pio = &ch_sge_dbg->tp_pio; + u32 *buff = ch_sge_dbg->outbuf; + + sge_pio->ireg_addr = t5_sge_dbg_index_array[i][0]; + sge_pio->ireg_data = t5_sge_dbg_index_array[i][1]; + sge_pio->ireg_local_offset = t5_sge_dbg_index_array[i][2]; + sge_pio->ireg_offset_range = t5_sge_dbg_index_array[i][3]; + + t4_read_indirect(padap, + sge_pio->ireg_addr, + sge_pio->ireg_data, + buff, + sge_pio->ireg_offset_range, + sge_pio->ireg_local_offset); + + ch_sge_dbg++; + } + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_full(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + u32 reg_addr, reg_data, reg_local_offset, reg_offset_range; + u32 *sp; + int rc; + int nreg = 0; + + /* Collect Registers: + * TP_DBG_SCHED_TX (0x7e40 + 0x6a), + * TP_DBG_SCHED_RX (0x7e40 + 0x6b), + * TP_DBG_CSIDE_INT (0x7e40 + 0x23f), + * TP_DBG_ESIDE_INT (0x7e40 + 0x148), + * PCIE_CDEBUG_INDEX[AppData0] (0x5a10 + 2), + * PCIE_CDEBUG_INDEX[AppData1] (0x5a10 + 3) This is for T6 + * SGE_DEBUG_DATA_HIGH_INDEX_10 (0x12a8) + **/ + + if (is_t5(padap)) + nreg = 6; + else if (is_t6(padap)) + nreg = 7; + + scratch_buff.size = nreg * sizeof(u32); + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + sp = (u32 *)scratch_buff.data; + + /* TP_DBG_SCHED_TX */ + reg_local_offset = t5_tp_pio_array[3][2] + 0xa; + reg_offset_range = 1; + + t4_tp_pio_read(padap, sp, reg_offset_range, reg_local_offset, true); + + sp++; + + /* TP_DBG_SCHED_RX */ + reg_local_offset = t5_tp_pio_array[3][2] + 0xb; + reg_offset_range = 1; + + t4_tp_pio_read(padap, sp, reg_offset_range, reg_local_offset, true); + + sp++; + + /* TP_DBG_CSIDE_INT */ + reg_local_offset = t5_tp_pio_array[9][2] + 0xf; + reg_offset_range = 1; + + t4_tp_pio_read(padap, sp, reg_offset_range, reg_local_offset, true); + + sp++; + + /* TP_DBG_ESIDE_INT */ + reg_local_offset = t5_tp_pio_array[8][2] + 3; + reg_offset_range = 1; + + t4_tp_pio_read(padap, sp, reg_offset_range, reg_local_offset, true); + + sp++; + + /* PCIE_CDEBUG_INDEX[AppData0] */ + reg_addr = t5_pcie_cdbg_array[0][0]; + reg_data = t5_pcie_cdbg_array[0][1]; + reg_local_offset = t5_pcie_cdbg_array[0][2] + 2; + reg_offset_range = 1; + + t4_read_indirect(padap, reg_addr, reg_data, sp, reg_offset_range, + reg_local_offset); + + sp++; + + if (is_t6(padap)) { + /* PCIE_CDEBUG_INDEX[AppData1] */ + reg_addr = t5_pcie_cdbg_array[0][0]; + reg_data = t5_pcie_cdbg_array[0][1]; + reg_local_offset = t5_pcie_cdbg_array[0][2] + 3; + reg_offset_range = 1; + + t4_read_indirect(padap, reg_addr, reg_data, sp, + reg_offset_range, reg_local_offset); + + sp++; + } + + /* SGE_DEBUG_DATA_HIGH_INDEX_10 */ + *sp = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_10); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int collect_vpd_data(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ +#ifdef notyet + struct cudbg_buffer scratch_buff; + struct adapter *padap = pdbg_init->adap; + struct struct_vpd_data *vpd_data; + char vpd_ver[4]; + u32 fw_vers; + u32 size; + int rc; + + size = sizeof(struct struct_vpd_data); + scratch_buff.size = size; + + rc = get_scratch_buff(dbg_buff, scratch_buff.size, &scratch_buff); + if (rc) + goto err; + + vpd_data = (struct struct_vpd_data *)scratch_buff.data; + + if (is_t5(padap)) { + read_vpd_reg(padap, SN_REG_ADDR, SN_MAX_LEN, vpd_data->sn); + read_vpd_reg(padap, BN_REG_ADDR, BN_MAX_LEN, vpd_data->bn); + read_vpd_reg(padap, NA_REG_ADDR, NA_MAX_LEN, vpd_data->na); + read_vpd_reg(padap, MN_REG_ADDR, MN_MAX_LEN, vpd_data->mn); + } else if (is_t6(padap)) { + read_vpd_reg(padap, SN_T6_ADDR, SN_MAX_LEN, vpd_data->sn); + read_vpd_reg(padap, BN_T6_ADDR, BN_MAX_LEN, vpd_data->bn); + read_vpd_reg(padap, NA_T6_ADDR, NA_MAX_LEN, vpd_data->na); + read_vpd_reg(padap, MN_T6_ADDR, MN_MAX_LEN, vpd_data->mn); + } + + if (is_fw_attached(pdbg_init)) { + rc = t4_get_scfg_version(padap, &vpd_data->scfg_vers); + } else { + rc = 1; + } + + if (rc) { + /* Now trying with backdoor mechanism */ + rc = read_vpd_reg(padap, SCFG_VER_ADDR, SCFG_VER_LEN, + (u8 *)&vpd_data->scfg_vers); + if (rc) + goto err1; + } + + if (is_fw_attached(pdbg_init)) { + rc = t4_get_vpd_version(padap, &vpd_data->vpd_vers); + } else { + rc = 1; + } + + if (rc) { + /* Now trying with backdoor mechanism */ + rc = read_vpd_reg(padap, VPD_VER_ADDR, VPD_VER_LEN, + (u8 *)vpd_ver); + if (rc) + goto err1; + /* read_vpd_reg return string of stored hex + * converting hex string to char string + * vpd version is 2 bytes only */ + sprintf(vpd_ver, "%c%c\n", vpd_ver[0], vpd_ver[1]); + vpd_data->vpd_vers = simple_strtoul(vpd_ver, NULL, 16); + } + + /* Get FW version if it's not already filled in */ + fw_vers = padap->params.fw_vers; + if (!fw_vers) { + rc = t4_get_fw_version(padap, &fw_vers); + if (rc) + goto err1; + } + + vpd_data->fw_major = G_FW_HDR_FW_VER_MAJOR(fw_vers); + vpd_data->fw_minor = G_FW_HDR_FW_VER_MINOR(fw_vers); + vpd_data->fw_micro = G_FW_HDR_FW_VER_MICRO(fw_vers); + vpd_data->fw_build = G_FW_HDR_FW_VER_BUILD(fw_vers); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +#endif + return (EDOOFUS); +} Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.h (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.h (revision 322022) @@ -0,0 +1,255 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef __CUDBG_LIB_H__ +#define __CUDBG_LIB_H__ + +#ifndef min_t +#define min_t(type, _a, _b) (((type)(_a) < (type)(_b)) ? (type)(_a) : (type)(_b)) +#endif + +static int collect_reg_dump(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_fw_devlog(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_qcfg(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ma_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_ulp0(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_ulp1(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_ulp2(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_ulp3(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_sge(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_obq_ncsi(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_tp0(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_tp1(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_ulp(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_sge0(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_sge1(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_ibq_ncsi(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_edc0_meminfo(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_edc1_meminfo(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_mc0_meminfo(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_mc1_meminfo(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rss(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rss_key(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rss_pf_config(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rss_vf_config(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rss_config(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_path_mtu(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_sw_state(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +int collect_wtp_data(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_pm_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_hw_sched(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tcp_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tp_err_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_fcoe_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_rdma_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tp_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_sge_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cpl_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_ddp_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_wc_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_ulprx_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_lb_stats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tp_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_meminfo(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cim_pif_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_clk_info(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_obq_sge_rx_q0(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_obq_sge_rx_q1(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_macstats(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_pcie_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_pm_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_full(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tx_rate(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_tid(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_pcie_config(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_dump_context(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_mps_tcam(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_vpd_data(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_le_tcam(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_cctrl(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_ma_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_ulptx_la(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_up_cim_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_pbt_tables(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_mbox_log(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); +static int collect_hma_indirect(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *); + +static int (*process_entity[]) + (struct cudbg_init *, struct cudbg_buffer *, struct cudbg_error *) = { + collect_reg_dump, + collect_fw_devlog, + collect_cim_la, /*3*/ + collect_cim_ma_la, + collect_cim_qcfg, + collect_cim_ibq_tp0, + collect_cim_ibq_tp1, + collect_cim_ibq_ulp, + collect_cim_ibq_sge0, + collect_cim_ibq_sge1, + collect_cim_ibq_ncsi, + collect_cim_obq_ulp0, + collect_cim_obq_ulp1, /*13*/ + collect_cim_obq_ulp2, + collect_cim_obq_ulp3, + collect_cim_obq_sge, + collect_cim_obq_ncsi, + collect_edc0_meminfo, + collect_edc1_meminfo, + collect_mc0_meminfo, + collect_mc1_meminfo, + collect_rss, /*22*/ + collect_rss_pf_config, + collect_rss_key, + collect_rss_vf_config, + collect_rss_config, /*26*/ + collect_path_mtu, /*27*/ + collect_sw_state, + collect_wtp_data, + collect_pm_stats, + collect_hw_sched, + collect_tcp_stats, + collect_tp_err_stats, + collect_fcoe_stats, + collect_rdma_stats, + collect_tp_indirect, + collect_sge_indirect, + collect_cpl_stats, + collect_ddp_stats, + collect_wc_stats, + collect_ulprx_la, + collect_lb_stats, + collect_tp_la, + collect_meminfo, + collect_cim_pif_la, + collect_clk_info, + collect_obq_sge_rx_q0, + collect_obq_sge_rx_q1, + collect_macstats, + collect_pcie_indirect, + collect_pm_indirect, + collect_full, + collect_tx_rate, + collect_tid, + collect_pcie_config, + collect_dump_context, + collect_mps_tcam, + collect_vpd_data, + collect_le_tcam, + collect_cctrl, + collect_ma_indirect, + collect_ulptx_la, + NULL, /* ext entity */ + collect_up_cim_indirect, + collect_pbt_tables, + collect_mbox_log, + collect_hma_indirect, + }; + +struct large_entity { + int entity_code; + int skip_flag; + int priority; /* 1 is high priority */ +}; + +static int read_cim_ibq(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error * , int); +static int read_cim_obq(struct cudbg_init *, struct cudbg_buffer *, + struct cudbg_error *, int); +int get_entity_hdr(void *outbuf, int i, u32 size, struct cudbg_entity_hdr **); +void skip_entity(int entity_code); +void reset_skip_entity(void); +int is_large_entity(int entity_code); +#endif Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib_common.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib_common.h (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib_common.h (revision 322022) @@ -0,0 +1,174 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * + * $FreeBSD$ + * + */ + +#ifndef __CUDBG_LIB_COMMON_H__ +#define __CUDBG_LIB_COMMON_H__ + +/* Extended entity + * + * Layout of the cudbg dump file when extended entity is present. + * + * + * ---------------- + * | Global header | + * |---------------| + * |entity headers | + * |---------------| + * | Entity data | + * | * | + * | * | + * | * | + * |---------------| + * |extended entity| + * | header | + * |---------------| + * |extended entity| + * | data | + * ----------------- + * + * + * Extended entity: This comes into picture only when cudbg_collect() is called + * multiple times. + */ + +#ifndef CUDBG_LITE +#include "common/t4_hw.h" +#endif + +#define CUDBG_SF_MAX_SECTOR (FLASH_CUDBG_START_SEC + FLASH_CUDBG_NSECS) +#define CUDBG_SF_SECTOR_SIZE SF_SEC_SIZE +#define CUDBG_START_SEC FLASH_CUDBG_START_SEC +#define CUDBG_FLASH_SIZE FLASH_CUDBG_MAX_SIZE + +#define CUDBG_EXT_DATA_BIT 0 +#define CUDBG_EXT_DATA_VALID (1 << CUDBG_EXT_DATA_BIT) + +struct cudbg_hdr { + u32 signature; + u32 hdr_len; + u16 major_ver; + u16 minor_ver; + u32 data_len; + u32 hdr_flags; + u16 max_entities; + u8 chip_ver; + u8 reserved1; + u32 reserved[8]; +}; + +struct cudbg_entity_hdr { + u32 entity_type; + u32 start_offset; + u32 size; + int hdr_flags; + u32 sys_warn; + u32 sys_err; + u8 num_pad; + u8 flag; /* bit 0 is used to indicate ext data */ + u8 reserved1[2]; + u32 next_ext_offset; /* pointer to next extended entity meta data */ + u32 reserved[5]; +}; + +struct cudbg_ver_hdr { + u32 signature; + u16 revision; + u16 size; +}; + +struct cudbg_buffer { + u32 size; + u32 offset; + char *data; +}; + +struct cudbg_error { + int sys_err; + int sys_warn; + int app_err; +}; + +struct cudbg_flash_sec_info { + int par_sec; /* Represent partially filled sector no */ + int par_sec_offset; /* Offset in partially filled sector */ + int cur_seq_no; + u32 max_seq_no; + u32 max_seq_sec; + u32 hdr_data_len; /* Total data */ + u32 skip_size; /* Total size of large entities. */ + u64 max_timestamp; + char sec_data[CUDBG_SF_SECTOR_SIZE]; + u8 sec_bitmap[8]; +}; + +struct cudbg_private { + struct cudbg_init dbg_init; + struct cudbg_flash_sec_info sec_info; +}; + +#define HTONL_NIBBLE(data) ( \ + (((uint32_t)(data) >> 28) & 0x0000000F) | \ + (((uint32_t)(data) >> 20) & 0x000000F0) | \ + (((uint32_t)(data) >> 12) & 0x00000F00) | \ + (((uint32_t)(data) >> 4) & 0x0000F000) | \ + (((uint32_t)(data) << 4) & 0x000F0000) | \ + (((uint32_t)(data) << 12) & 0x00F00000) | \ + (((uint32_t)(data) << 20) & 0x0F000000) | \ + (((uint32_t)(data) << 28) & 0xF0000000)) + +#define CDUMP_MAX_COMP_BUF_SIZE ((64 * 1024) - 1) +#define CUDBG_CHUNK_SIZE ((CDUMP_MAX_COMP_BUF_SIZE/1024) * 1024) + +#define CUDBG_LEGACY_SIGNATURE 123 +#define CUDBG_SIGNATURE 67856866 /* CUDB in ascii */ +#define CUDBG_FL_SIGNATURE 0x4355464c /* CUFL in ascii */ + +#define CUDBG_FL_MAJOR_VERSION 1 +#define CUDBG_FL_MINOR_VERSION 1 +#define CUDBG_FL_BUILD_VERSION 0 + +void update_skip_size(struct cudbg_flash_sec_info *, u32); +int write_compression_hdr(struct cudbg_buffer *, struct cudbg_buffer *); +int compress_buff(struct cudbg_buffer *, struct cudbg_buffer *); +int get_scratch_buff(struct cudbg_buffer *, u32, struct cudbg_buffer *); +void release_scratch_buff(struct cudbg_buffer *, struct cudbg_buffer *); +int decompress_buffer(struct cudbg_buffer *, struct cudbg_buffer *); +int validate_buffer(struct cudbg_buffer *compressed_buffer); +int decompress_buffer_wrapper(struct cudbg_buffer *pc_buff, + struct cudbg_buffer *pdc_buff); +int get_entity_rev(struct cudbg_ver_hdr *ver_hdr); +void sort_t(void *base, int num, int size, + int (*cmp_func)(const void *, const void *), + void (*swap_func)(void *, void *, int size)); +int cudbg_read_flash(void *handle, void *data, u32 size, int data_flag); +int cudbg_write_flash(void *handle, u64 timestamp, void *data, + u32 start_offset, u32 start_hdr_offset, + u32 cur_entity_size, + u32 ext_size); +#endif Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_lib_common.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_wtp.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_wtp.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_wtp.c (revision 322022) @@ -0,0 +1,1310 @@ +/*- + * Copyright (c) 2017 Chelsio Communications, Inc. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE + * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS + * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT + * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY + * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + */ + +#include +__FBSDID("$FreeBSD$"); + +#include +#include + +#include "common/common.h" +#include "common/t4_regs.h" +#include "cudbg.h" +#include "cudbg_lib_common.h" +#include "cudbg_entity.h" + +int collect_wtp_data(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err); +/*SGE_DEBUG Registers.*/ +#define TP_MIB_SIZE 0x5e + +struct sge_debug_reg_data { + /*indx0*/ + u32 reserved1:4; + u32 reserved2:4; + u32 debug_uP_SOP_cnt:4; + u32 debug_uP_EOP_cnt:4; + u32 debug_CIM_SOP1_cnt:4; + u32 debug_CIM_EOP1_cnt:4; + u32 debug_CIM_SOP0_cnt:4; + u32 debug_CIM_EOP0_cnt:4; + + /*indx1*/ + u32 reserved3:32; + + /*indx2*/ + u32 debug_T_Rx_SOP1_cnt:4; + u32 debug_T_Rx_EOP1_cnt:4; + u32 debug_T_Rx_SOP0_cnt:4; + u32 debug_T_Rx_EOP0_cnt:4; + u32 debug_U_Rx_SOP1_cnt:4; + u32 debug_U_Rx_EOP1_cnt:4; + u32 debug_U_Rx_SOP0_cnt:4; + u32 debug_U_Rx_EOP0_cnt:4; + + /*indx3*/ + u32 reserved4:32; + + /*indx4*/ + u32 debug_UD_Rx_SOP3_cnt:4; + u32 debug_UD_Rx_EOP3_cnt:4; + u32 debug_UD_Rx_SOP2_cnt:4; + u32 debug_UD_Rx_EOP2_cnt:4; + u32 debug_UD_Rx_SOP1_cnt:4; + u32 debug_UD_Rx_EOP1_cnt:4; + u32 debug_UD_Rx_SOP0_cnt:4; + u32 debug_UD_Rx_EOP0_cnt:4; + + /*indx5*/ + u32 reserved5:32; + + /*indx6*/ + u32 debug_U_Tx_SOP3_cnt:4; + u32 debug_U_Tx_EOP3_cnt:4; + u32 debug_U_Tx_SOP2_cnt:4; + u32 debug_U_Tx_EOP2_cnt:4; + u32 debug_U_Tx_SOP1_cnt:4; + u32 debug_U_Tx_EOP1_cnt:4; + u32 debug_U_Tx_SOP0_cnt:4; + u32 debug_U_Tx_EOP0_cnt:4; + + /*indx7*/ + u32 reserved6:32; + + /*indx8*/ + u32 debug_PC_Rsp_SOP1_cnt:4; + u32 debug_PC_Rsp_EOP1_cnt:4; + u32 debug_PC_Rsp_SOP0_cnt:4; + u32 debug_PC_Rsp_EOP0_cnt:4; + u32 debug_PC_Req_SOP1_cnt:4; + u32 debug_PC_Req_EOP1_cnt:4; + u32 debug_PC_Req_SOP0_cnt:4; + u32 debug_PC_Req_EOP0_cnt:4; + + /*indx9*/ + u32 reserved7:32; + + /*indx10*/ + u32 debug_PD_Req_SOP3_cnt:4; + u32 debug_PD_Req_EOP3_cnt:4; + u32 debug_PD_Req_SOP2_cnt:4; + u32 debug_PD_Req_EOP2_cnt:4; + u32 debug_PD_Req_SOP1_cnt:4; + u32 debug_PD_Req_EOP1_cnt:4; + u32 debug_PD_Req_SOP0_cnt:4; + u32 debug_PD_Req_EOP0_cnt:4; + + /*indx11*/ + u32 reserved8:32; + + /*indx12*/ + u32 debug_PD_Rsp_SOP3_cnt:4; + u32 debug_PD_Rsp_EOP3_cnt:4; + u32 debug_PD_Rsp_SOP2_cnt:4; + u32 debug_PD_Rsp_EOP2_cnt:4; + u32 debug_PD_Rsp_SOP1_cnt:4; + u32 debug_PD_Rsp_EOP1_cnt:4; + u32 debug_PD_Rsp_SOP0_cnt:4; + u32 debug_PD_Rsp_EOP0_cnt:4; + + /*indx13*/ + u32 reserved9:32; + + /*indx14*/ + u32 debug_CPLSW_TP_Rx_SOP1_cnt:4; + u32 debug_CPLSW_TP_Rx_EOP1_cnt:4; + u32 debug_CPLSW_TP_Rx_SOP0_cnt:4; + u32 debug_CPLSW_TP_Rx_EOP0_cnt:4; + u32 debug_CPLSW_CIM_SOP1_cnt:4; + u32 debug_CPLSW_CIM_EOP1_cnt:4; + u32 debug_CPLSW_CIM_SOP0_cnt:4; + u32 debug_CPLSW_CIM_EOP0_cnt:4; + + /*indx15*/ + u32 reserved10:32; + + /*indx16*/ + u32 debug_PD_Req_Rd3_cnt:4; + u32 debug_PD_Req_Rd2_cnt:4; + u32 debug_PD_Req_Rd1_cnt:4; + u32 debug_PD_Req_Rd0_cnt:4; + u32 debug_PD_Req_Int3_cnt:4; + u32 debug_PD_Req_Int2_cnt:4; + u32 debug_PD_Req_Int1_cnt:4; + u32 debug_PD_Req_Int0_cnt:4; + +}; + +struct tp_mib_type tp_mib[] = { + {"tp_mib_mac_in_err_0", 0x0}, + {"tp_mib_mac_in_err_1", 0x1}, + {"tp_mib_mac_in_err_2", 0x2}, + {"tp_mib_mac_in_err_3", 0x3}, + {"tp_mib_hdr_in_err_0", 0x4}, + {"tp_mib_hdr_in_err_1", 0x5}, + {"tp_mib_hdr_in_err_2", 0x6}, + {"tp_mib_hdr_in_err_3", 0x7}, + {"tp_mib_tcp_in_err_0", 0x8}, + {"tp_mib_tcp_in_err_1", 0x9}, + {"tp_mib_tcp_in_err_2", 0xa}, + {"tp_mib_tcp_in_err_3", 0xb}, + {"tp_mib_tcp_out_rst", 0xc}, + {"tp_mib_tcp_in_seg_hi", 0x10}, + {"tp_mib_tcp_in_seg_lo", 0x11}, + {"tp_mib_tcp_out_seg_hi", 0x12}, + {"tp_mib_tcp_out_seg_lo", 0x13}, + {"tp_mib_tcp_rxt_seg_hi", 0x14}, + {"tp_mib_tcp_rxt_seg_lo", 0x15}, + {"tp_mib_tnl_cng_drop_0", 0x18}, + {"tp_mib_tnl_cng_drop_1", 0x19}, + {"tp_mib_tnl_cng_drop_2", 0x1a}, + {"tp_mib_tnl_cng_drop_3", 0x1b}, + {"tp_mib_ofd_chn_drop_0", 0x1c}, + {"tp_mib_ofd_chn_drop_1", 0x1d}, + {"tp_mib_ofd_chn_drop_2", 0x1e}, + {"tp_mib_ofd_chn_drop_3", 0x1f}, + {"tp_mib_tnl_out_pkt_0", 0x20}, + {"tp_mib_tnl_out_pkt_1", 0x21}, + {"tp_mib_tnl_out_pkt_2", 0x22}, + {"tp_mib_tnl_out_pkt_3", 0x23}, + {"tp_mib_tnl_in_pkt_0", 0x24}, + {"tp_mib_tnl_in_pkt_1", 0x25}, + {"tp_mib_tnl_in_pkt_2", 0x26}, + {"tp_mib_tnl_in_pkt_3", 0x27}, + {"tp_mib_tcp_v6in_err_0", 0x28}, + {"tp_mib_tcp_v6in_err_1", 0x29}, + {"tp_mib_tcp_v6in_err_2", 0x2a}, + {"tp_mib_tcp_v6in_err_3", 0x2b}, + {"tp_mib_tcp_v6out_rst", 0x2c}, + {"tp_mib_tcp_v6in_seg_hi", 0x30}, + {"tp_mib_tcp_v6in_seg_lo", 0x31}, + {"tp_mib_tcp_v6out_seg_hi", 0x32}, + {"tp_mib_tcp_v6out_seg_lo", 0x33}, + {"tp_mib_tcp_v6rxt_seg_hi", 0x34}, + {"tp_mib_tcp_v6rxt_seg_lo", 0x35}, + {"tp_mib_ofd_arp_drop", 0x36}, + {"tp_mib_ofd_dfr_drop", 0x37}, + {"tp_mib_cpl_in_req_0", 0x38}, + {"tp_mib_cpl_in_req_1", 0x39}, + {"tp_mib_cpl_in_req_2", 0x3a}, + {"tp_mib_cpl_in_req_3", 0x3b}, + {"tp_mib_cpl_out_rsp_0", 0x3c}, + {"tp_mib_cpl_out_rsp_1", 0x3d}, + {"tp_mib_cpl_out_rsp_2", 0x3e}, + {"tp_mib_cpl_out_rsp_3", 0x3f}, + {"tp_mib_tnl_lpbk_0", 0x40}, + {"tp_mib_tnl_lpbk_1", 0x41}, + {"tp_mib_tnl_lpbk_2", 0x42}, + {"tp_mib_tnl_lpbk_3", 0x43}, + {"tp_mib_tnl_drop_0", 0x44}, + {"tp_mib_tnl_drop_1", 0x45}, + {"tp_mib_tnl_drop_2", 0x46}, + {"tp_mib_tnl_drop_3", 0x47}, + {"tp_mib_fcoe_ddp_0", 0x48}, + {"tp_mib_fcoe_ddp_1", 0x49}, + {"tp_mib_fcoe_ddp_2", 0x4a}, + {"tp_mib_fcoe_ddp_3", 0x4b}, + {"tp_mib_fcoe_drop_0", 0x4c}, + {"tp_mib_fcoe_drop_1", 0x4d}, + {"tp_mib_fcoe_drop_2", 0x4e}, + {"tp_mib_fcoe_drop_3", 0x4f}, + {"tp_mib_fcoe_byte_0_hi", 0x50}, + {"tp_mib_fcoe_byte_0_lo", 0x51}, + {"tp_mib_fcoe_byte_1_hi", 0x52}, + {"tp_mib_fcoe_byte_1_lo", 0x53}, + {"tp_mib_fcoe_byte_2_hi", 0x54}, + {"tp_mib_fcoe_byte_2_lo", 0x55}, + {"tp_mib_fcoe_byte_3_hi", 0x56}, + {"tp_mib_fcoe_byte_3_lo", 0x57}, + {"tp_mib_ofd_vln_drop_0", 0x58}, + {"tp_mib_ofd_vln_drop_1", 0x59}, + {"tp_mib_ofd_vln_drop_2", 0x5a}, + {"tp_mib_ofd_vln_drop_3", 0x5b}, + {"tp_mib_usm_pkts", 0x5c}, + {"tp_mib_usm_drop", 0x5d}, + {"tp_mib_usm_bytes_hi", 0x5e}, + {"tp_mib_usm_bytes_lo", 0x5f}, + {"tp_mib_tid_del", 0x60}, + {"tp_mib_tid_inv", 0x61}, + {"tp_mib_tid_act", 0x62}, + {"tp_mib_tid_pas", 0x63}, + {"tp_mib_rqe_dfr_mod", 0x64}, + {"tp_mib_rqe_dfr_pkt", 0x65} +}; + +static u32 read_sge_debug_data(struct cudbg_init *pdbg_init, u32 *sge_dbg_reg) +{ + struct adapter *padap = pdbg_init->adap; + u32 value; + int i = 0; + + for (i = 0; i <= 15; i++) { + t4_write_reg(padap, A_SGE_DEBUG_INDEX, (u32)i); + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_LOW); + /*printf("LOW 0x%08x\n", value);*/ + sge_dbg_reg[(i << 1) | 1] = HTONL_NIBBLE(value); + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH); + /*printf("HIGH 0x%08x\n", value);*/ + sge_dbg_reg[(i << 1)] = HTONL_NIBBLE(value); + } + return 0; +} + +static u32 read_tp_mib_data(struct cudbg_init *pdbg_init, + struct tp_mib_data **ppTp_Mib) +{ + struct adapter *padap = pdbg_init->adap; + u32 i = 0; + + for (i = 0; i < TP_MIB_SIZE; i++) { + t4_tp_mib_read(padap, &tp_mib[i].value, 1, + (u32)tp_mib[i].addr, true); + } + *ppTp_Mib = (struct tp_mib_data *)&tp_mib[0]; + + return 0; +} + +static int t5_wtp_data(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct sge_debug_reg_data *sge_dbg_reg = NULL; + struct cudbg_buffer scratch_buff; + struct tp_mib_data *ptp_mib = NULL; + struct wtp_data *wtp; + u32 Sge_Dbg[32] = {0}; + u32 value = 0; + u32 i = 0; + u32 drop = 0; + u32 err = 0; + u32 offset; + int rc = 0; + + rc = get_scratch_buff(dbg_buff, sizeof(struct wtp_data), &scratch_buff); + + if (rc) + goto err; + + offset = scratch_buff.offset; + wtp = (struct wtp_data *)((char *)scratch_buff.data + offset); + + read_sge_debug_data(pdbg_init, Sge_Dbg); + read_tp_mib_data(pdbg_init, &ptp_mib); + + sge_dbg_reg = (struct sge_debug_reg_data *) &Sge_Dbg[0]; + + /*#######################################################################*/ + /*# TX PATH, starting from pcie*/ + /*#######################################################################*/ + + /* Get Reqests of commmands from SGE to PCIE*/ + + wtp->sge_pcie_cmd_req.sop[0] = sge_dbg_reg->debug_PC_Req_SOP0_cnt; + wtp->sge_pcie_cmd_req.sop[1] = sge_dbg_reg->debug_PC_Req_SOP1_cnt; + + wtp->sge_pcie_cmd_req.eop[0] = sge_dbg_reg->debug_PC_Req_EOP0_cnt; + wtp->sge_pcie_cmd_req.eop[1] = sge_dbg_reg->debug_PC_Req_EOP1_cnt; + + /* Get Reqests of commmands from PCIE to core*/ + value = t4_read_reg(padap, A_PCIE_CMDR_REQ_CNT); + + wtp->pcie_core_cmd_req.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_cmd_req.sop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + /* there is no EOP for this, so we fake it.*/ + wtp->pcie_core_cmd_req.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_cmd_req.eop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + + /* Get DMA stats*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, A_PCIE_T5_DMA_STAT3 + (i * 0x10)); + wtp->pcie_t5_dma_stat3.sop[i] = value & 0xFF; + wtp->pcie_t5_dma_stat3.eop[i] = ((value >> 16) & 0xFF); + } + + /* Get SGE debug data high index 6*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_6); + wtp->sge_debug_data_high_index_6.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_debug_data_high_index_6.eop[0] = ((value >> 0) & 0x0F); + wtp->sge_debug_data_high_index_6.sop[1] = ((value >> 12) & 0x0F); + wtp->sge_debug_data_high_index_6.eop[1] = ((value >> 8) & 0x0F); + wtp->sge_debug_data_high_index_6.sop[2] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_index_6.eop[2] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_index_6.sop[3] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_index_6.eop[3] = ((value >> 24) & 0x0F); + + /* Get SGE debug data high index 3*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_3); + wtp->sge_debug_data_high_index_3.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_debug_data_high_index_3.eop[0] = ((value >> 0) & 0x0F); + wtp->sge_debug_data_high_index_3.sop[1] = ((value >> 12) & 0x0F); + wtp->sge_debug_data_high_index_3.eop[1] = ((value >> 8) & 0x0F); + wtp->sge_debug_data_high_index_3.sop[2] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_index_3.eop[2] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_index_3.sop[3] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_index_3.eop[3] = ((value >> 24) & 0x0F); + + /* Get ULP SE CNT CHx*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, A_ULP_TX_SE_CNT_CH0 + (i * 4)); + wtp->ulp_se_cnt_chx.sop[i] = ((value >> 28) & 0x0F); + wtp->ulp_se_cnt_chx.eop[i] = ((value >> 24) & 0x0F); + } + + /* Get MAC PORTx PKT COUNT*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, 0x3081c + ((i * 4) << 12)); + wtp->mac_portx_pkt_count.sop[i] = ((value >> 24) & 0xFF); + wtp->mac_portx_pkt_count.eop[i] = ((value >> 16) & 0xFF); + wtp->mac_porrx_pkt_count.sop[i] = ((value >> 8) & 0xFF); + wtp->mac_porrx_pkt_count.eop[i] = ((value >> 0) & 0xFF); + } + + /* Get mac portx aFramesTransmittedok*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, 0x30a80 + ((i * 4) << 12)); + wtp->mac_portx_aframestra_ok.sop[i] = (value & 0xFF); + wtp->mac_portx_aframestra_ok.eop[i] = (value & 0xFF); + } + + /* Get command respones from core to PCIE*/ + value = t4_read_reg(padap, A_PCIE_CMDR_RSP_CNT); + + wtp->core_pcie_cmd_rsp.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->core_pcie_cmd_rsp.sop[1] = ((value >> 16) & 0xFF); /*bit 16:23*/ + + wtp->core_pcie_cmd_rsp.eop[0] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->core_pcie_cmd_rsp.eop[1] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + /*Get command Resposes from PCIE to SGE*/ + wtp->pcie_sge_cmd_rsp.sop[0] = sge_dbg_reg->debug_PC_Rsp_SOP0_cnt; + wtp->pcie_sge_cmd_rsp.sop[1] = sge_dbg_reg->debug_PC_Rsp_SOP1_cnt; + + wtp->pcie_sge_cmd_rsp.eop[0] = sge_dbg_reg->debug_PC_Rsp_EOP0_cnt; + wtp->pcie_sge_cmd_rsp.eop[1] = sge_dbg_reg->debug_PC_Rsp_EOP1_cnt; + + /* Get commands sent from SGE to CIM/uP*/ + wtp->sge_cim.sop[0] = sge_dbg_reg->debug_CIM_SOP0_cnt; + wtp->sge_cim.sop[1] = sge_dbg_reg->debug_CIM_SOP1_cnt; + + wtp->sge_cim.eop[0] = sge_dbg_reg->debug_CIM_EOP0_cnt; + wtp->sge_cim.eop[1] = sge_dbg_reg->debug_CIM_EOP1_cnt; + + /* Get Reqests of data from PCIE by SGE*/ + wtp->utx_sge_dma_req.sop[0] = sge_dbg_reg->debug_UD_Rx_SOP0_cnt; + wtp->utx_sge_dma_req.sop[1] = sge_dbg_reg->debug_UD_Rx_SOP1_cnt; + wtp->utx_sge_dma_req.sop[2] = sge_dbg_reg->debug_UD_Rx_SOP2_cnt; + wtp->utx_sge_dma_req.sop[3] = sge_dbg_reg->debug_UD_Rx_SOP3_cnt; + + wtp->utx_sge_dma_req.eop[0] = sge_dbg_reg->debug_UD_Rx_EOP0_cnt; + wtp->utx_sge_dma_req.eop[1] = sge_dbg_reg->debug_UD_Rx_EOP1_cnt; + wtp->utx_sge_dma_req.eop[2] = sge_dbg_reg->debug_UD_Rx_EOP2_cnt; + wtp->utx_sge_dma_req.eop[3] = sge_dbg_reg->debug_UD_Rx_EOP3_cnt; + + /* Get Reqests of data from PCIE by SGE*/ + wtp->sge_pcie_dma_req.sop[0] = sge_dbg_reg->debug_PD_Req_Rd0_cnt; + wtp->sge_pcie_dma_req.sop[1] = sge_dbg_reg->debug_PD_Req_Rd1_cnt; + wtp->sge_pcie_dma_req.sop[2] = sge_dbg_reg->debug_PD_Req_Rd2_cnt; + wtp->sge_pcie_dma_req.sop[3] = sge_dbg_reg->debug_PD_Req_Rd3_cnt; + /*no EOP's, so fake it.*/ + wtp->sge_pcie_dma_req.eop[0] = sge_dbg_reg->debug_PD_Req_Rd0_cnt; + wtp->sge_pcie_dma_req.eop[1] = sge_dbg_reg->debug_PD_Req_Rd1_cnt; + wtp->sge_pcie_dma_req.eop[2] = sge_dbg_reg->debug_PD_Req_Rd2_cnt; + wtp->sge_pcie_dma_req.eop[3] = sge_dbg_reg->debug_PD_Req_Rd3_cnt; + + /* Get Reqests of data from PCIE to core*/ + value = t4_read_reg(padap, A_PCIE_DMAR_REQ_CNT); + + wtp->pcie_core_dma_req.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dma_req.sop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dma_req.sop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dma_req.sop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + /* There is no eop so fake it.*/ + wtp->pcie_core_dma_req.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dma_req.eop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dma_req.eop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dma_req.eop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + /* Get data responses from core to PCIE*/ + value = t4_read_reg(padap, A_PCIE_DMAR_RSP_SOP_CNT); + + wtp->core_pcie_dma_rsp.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->core_pcie_dma_rsp.sop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->core_pcie_dma_rsp.sop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->core_pcie_dma_rsp.sop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + value = t4_read_reg(padap, A_PCIE_DMAR_RSP_EOP_CNT); + + wtp->core_pcie_dma_rsp.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->core_pcie_dma_rsp.eop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->core_pcie_dma_rsp.eop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->core_pcie_dma_rsp.eop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + /* Get PCIE_DATA to SGE*/ + wtp->pcie_sge_dma_rsp.sop[0] = sge_dbg_reg->debug_PD_Rsp_SOP0_cnt; + wtp->pcie_sge_dma_rsp.sop[1] = sge_dbg_reg->debug_PD_Rsp_SOP1_cnt; + wtp->pcie_sge_dma_rsp.sop[2] = sge_dbg_reg->debug_PD_Rsp_SOP2_cnt; + wtp->pcie_sge_dma_rsp.sop[3] = sge_dbg_reg->debug_PD_Rsp_SOP3_cnt; + + wtp->pcie_sge_dma_rsp.eop[0] = sge_dbg_reg->debug_PD_Rsp_EOP0_cnt; + wtp->pcie_sge_dma_rsp.eop[1] = sge_dbg_reg->debug_PD_Rsp_EOP1_cnt; + wtp->pcie_sge_dma_rsp.eop[2] = sge_dbg_reg->debug_PD_Rsp_EOP2_cnt; + wtp->pcie_sge_dma_rsp.eop[3] = sge_dbg_reg->debug_PD_Rsp_EOP3_cnt; + + /*Get SGE to ULP_TX*/ + wtp->sge_utx.sop[0] = sge_dbg_reg->debug_U_Tx_SOP0_cnt; + wtp->sge_utx.sop[1] = sge_dbg_reg->debug_U_Tx_SOP1_cnt; + wtp->sge_utx.sop[2] = sge_dbg_reg->debug_U_Tx_SOP2_cnt; + wtp->sge_utx.sop[3] = sge_dbg_reg->debug_U_Tx_SOP3_cnt; + + wtp->sge_utx.eop[0] = sge_dbg_reg->debug_U_Tx_EOP0_cnt; + wtp->sge_utx.eop[1] = sge_dbg_reg->debug_U_Tx_EOP1_cnt; + wtp->sge_utx.eop[2] = sge_dbg_reg->debug_U_Tx_EOP2_cnt; + wtp->sge_utx.eop[3] = sge_dbg_reg->debug_U_Tx_EOP3_cnt; + + /* Get ULP_TX to TP*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, (A_ULP_TX_SE_CNT_CH0 + (i*4))); + + wtp->utx_tp.sop[i] = ((value >> 28) & 0xF); /*bits 28:31*/ + wtp->utx_tp.eop[i] = ((value >> 24) & 0xF); /*bits 24:27*/ + } + + /* Get TP_DBG_CSIDE registers*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_CSIDE_RX0 + i), + true); + + wtp->utx_tpcside.sop[i] = ((value >> 28) & 0xF);/*bits 28:31*/ + wtp->utx_tpcside.eop[i] = ((value >> 24) & 0xF);/*bits 24:27*/ + wtp->tpcside_rxpld.sop[i] = ((value >> 20) & 0xF);/*bits 20:23*/ + wtp->tpcside_rxpld.eop[i] = ((value >> 16) & 0xF);/*bits 16:19*/ + wtp->tpcside_rxarb.sop[i] = ((value >> 12) & 0xF);/*bits 12:15*/ + wtp->tpcside_rxarb.eop[i] = ((value >> 8) & 0xF); /*bits 8:11*/ + wtp->tpcside_rxcpl.sop[i] = ((value >> 4) & 0xF); /*bits 4:7*/ + wtp->tpcside_rxcpl.eop[i] = ((value >> 0) & 0xF); /*bits 0:3*/ + } + + /* TP_DBG_ESIDE*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_ESIDE_PKT0 + i), + true); + + wtp->tpeside_mps.sop[i] = ((value >> 28) & 0xF); /*bits 28:31*/ + wtp->tpeside_mps.eop[i] = ((value >> 24) & 0xF); /*bits 24:27*/ + wtp->tpeside_pm.sop[i] = ((value >> 20) & 0xF); /*bits 20:23*/ + wtp->tpeside_pm.eop[i] = ((value >> 16) & 0xF); /*bits 16:19*/ + wtp->mps_tpeside.sop[i] = ((value >> 12) & 0xF); /*bits 12:15*/ + wtp->mps_tpeside.eop[i] = ((value >> 8) & 0xF); /*bits 8:11*/ + wtp->tpeside_pld.sop[i] = ((value >> 4) & 0xF); /*bits 4:7*/ + wtp->tpeside_pld.eop[i] = ((value >> 0) & 0xF); /*bits 0:3*/ + + } + + /*PCIE CMD STAT2*/ + for (i = 0; i < 3; i++) { + value = t4_read_reg(padap, 0x5988 + (i * 0x10)); + wtp->pcie_cmd_stat2.sop[i] = value & 0xFF; + wtp->pcie_cmd_stat2.eop[i] = value & 0xFF; + } + + /*PCIE cmd stat3*/ + for (i = 0; i < 3; i++) { + value = t4_read_reg(padap, 0x598c + (i * 0x10)); + wtp->pcie_cmd_stat3.sop[i] = value & 0xFF; + wtp->pcie_cmd_stat3.eop[i] = value & 0xFF; + } + + /* ULP_RX input/output*/ + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_ULP_RX_SE_CNT_CH0 + (i*4))); + + wtp->pmrx_ulprx.sop[i] = ((value >> 4) & 0xF); /*bits 4:7*/ + wtp->pmrx_ulprx.eop[i] = ((value >> 0) & 0xF); /*bits 0:3*/ + wtp->ulprx_tpcside.sop[i] = ((value >> 28) & 0xF);/*bits 28:31*/ + wtp->ulprx_tpcside.eop[i] = ((value >> 24) & 0xF);/*bits 24:27*/ + } + + /* Get the MPS input from TP*/ + drop = 0; + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_TX_SE_CNT_TP01 + (i << 2))); + wtp->tp_mps.sop[(i*2)] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->tp_mps.eop[(i*2)] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->tp_mps.sop[(i*2) + 1] = ((value >> 24) & 0xFF);/*bit 24:31 + */ + wtp->tp_mps.eop[(i*2) + 1] = ((value >> 16) & 0xFF);/*bit 16:23 + */ + } + drop = ptp_mib->TP_MIB_OFD_ARP_DROP.value; + drop += ptp_mib->TP_MIB_OFD_DFR_DROP.value; + + drop += ptp_mib->TP_MIB_TNL_DROP_0.value; + drop += ptp_mib->TP_MIB_TNL_DROP_1.value; + drop += ptp_mib->TP_MIB_TNL_DROP_2.value; + drop += ptp_mib->TP_MIB_TNL_DROP_3.value; + + wtp->tp_mps.drops = drop; + + /* Get the MPS output to the MAC's*/ + drop = 0; + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_TX_SE_CNT_MAC01 + (i << 2))); + wtp->mps_xgm.sop[(i*2)] = ((value >> 8) & 0xFF);/*bit 8:15*/ + wtp->mps_xgm.eop[(i*2)] = ((value >> 0) & 0xFF);/*bit 0:7*/ + wtp->mps_xgm.sop[(i*2) + 1] = ((value >> 24) & 0xFF);/*bit 24:31 + */ + wtp->mps_xgm.eop[(i*2) + 1] = ((value >> 16) & 0xFF);/*bit 16:23 + */ + } + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_TX_PORT_DROP_L) + + (i * T5_PORT_STRIDE))); + drop += value; + } + wtp->mps_xgm.drops = (drop & 0xFF); + + /* Get the SOP/EOP counters into and out of MAC. [JHANEL] I think this + * is*/ + /* clear on read, so you have to read both TX and RX path at same + * time.*/ + drop = 0; + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MAC_PORT_PKT_COUNT) + + (i * T5_PORT_STRIDE))); + + wtp->tx_xgm_xgm.sop[i] = ((value >> 24) & 0xFF); /*bit 24:31*/ + wtp->tx_xgm_xgm.eop[i] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->rx_xgm_xgm.sop[i] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->rx_xgm_xgm.eop[i] = ((value >> 0) & 0xFF); /*bit 0:7*/ + } + + /* Get the MAC's output to the wire*/ + drop = 0; + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MAC_PORT_AFRAMESTRANSMITTEDOK) + + (i * T5_PORT_STRIDE))); + wtp->xgm_wire.sop[i] = (value); + wtp->xgm_wire.eop[i] = (value); /* No EOP for XGMAC, so fake + it.*/ + } + + /*########################################################################*/ + /*# RX PATH, starting from wire*/ + /*########################################################################*/ + + /* Add up the wire input to the MAC*/ + drop = 0; + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MAC_PORT_AFRAMESRECEIVEDOK) + + (i * T5_PORT_STRIDE))); + + wtp->wire_xgm.sop[i] = (value); + wtp->wire_xgm.eop[i] = (value); /* No EOP for XGMAC, so fake + it.*/ + } + + /* Already read the rx_xgm_xgm when reading TX path.*/ + + /* Add up SOP/EOP's on all 8 MPS buffer channels*/ + drop = 0; + for (i = 0; i < 8; i++) { + value = t4_read_reg(padap, (A_MPS_RX_SE_CNT_IN0 + (i << 2))); + + wtp->xgm_mps.sop[i] = ((value >> 8) & 0xFF); /*bits 8:15*/ + wtp->xgm_mps.eop[i] = ((value >> 0) & 0xFF); /*bits 0:7*/ + } + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, (A_MPS_RX_CLS_DROP_CNT0 + (i << 2))); + /* typo in JHANEL's code.*/ + drop += (value & 0xFFFF) + ((value >> 16) & 0xFFFF); + } + wtp->xgm_mps.cls_drop = drop & 0xFF; + + /* Add up the overflow drops on all 4 ports.*/ + drop = 0; + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 2))); + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_LB_DROP_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 2))); + + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + + value = t4_read_reg(padap, + T5_PORT0_REG(A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES) + + (i * T5_PORT_STRIDE)); + drop += value; + } + wtp->xgm_mps.drop = (drop & 0xFF); + + /* Add up the MPS errors that should result in dropped packets*/ + err = 0; + for (i = 0; i < 4; i++) { + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LESS_64B_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG((A_MPS_PORT_STAT_RX_PORT_LESS_64B_L) + + (i * T5_PORT_STRIDE) + 4))); + } + wtp->xgm_mps.err = (err & 0xFF); + + drop = 0; + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_RX_SE_CNT_OUT01 + (i << 2))); + + wtp->mps_tp.sop[(i*2)] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->mps_tp.eop[(i*2)] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->mps_tp.sop[(i*2) + 1] = ((value >> 24) & 0xFF);/*bit 24:31 + */ + wtp->mps_tp.eop[(i*2) + 1] = ((value >> 16) & 0xFF);/*bit 16:23 + */ + } + drop = ptp_mib->TP_MIB_TNL_CNG_DROP_0.value; + drop += ptp_mib->TP_MIB_TNL_CNG_DROP_1.value; + drop += ptp_mib->TP_MIB_TNL_CNG_DROP_2.value; + drop += ptp_mib->TP_MIB_TNL_CNG_DROP_3.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_0.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_1.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_2.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_3.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_0.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_1.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_2.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_3.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_0.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_1.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_2.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_3.value; + drop += ptp_mib->TP_MIB_USM_DROP.value; + + wtp->mps_tp.drops = drop; + + /* Get TP_DBG_CSIDE_TX registers*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_CSIDE_RX0 + i), + true); + + wtp->tpcside_csw.sop[i] = ((value >> 28) & 0xF);/*bits 28:31*/ + wtp->tpcside_csw.eop[i] = ((value >> 24) & 0xF);/*bits 24:27*/ + wtp->tpcside_pm.sop[i] = ((value >> 20) & 0xF);/*bits 20:23*/ + wtp->tpcside_pm.eop[i] = ((value >> 16) & 0xF);/*bits 16:19*/ + wtp->tpcside_uturn.sop[i] = ((value >> 12) & 0xF);/*bits 12:15*/ + wtp->tpcside_uturn.eop[i] = ((value >> 8) & 0xF); /*bits 8:11*/ + wtp->tpcside_txcpl.sop[i] = ((value >> 4) & 0xF); /*bits 4:7*/ + wtp->tpcside_txcpl.eop[i] = ((value >> 0) & 0xF); /*bits 0:3*/ + } + + /* TP to CPL_SWITCH*/ + wtp->tp_csw.sop[0] = sge_dbg_reg->debug_CPLSW_TP_Rx_SOP0_cnt; + wtp->tp_csw.sop[1] = sge_dbg_reg->debug_CPLSW_TP_Rx_SOP1_cnt; + + wtp->tp_csw.eop[0] = sge_dbg_reg->debug_CPLSW_TP_Rx_EOP0_cnt; + wtp->tp_csw.eop[1] = sge_dbg_reg->debug_CPLSW_TP_Rx_EOP1_cnt; + + /* TP/CPL_SWITCH to SGE*/ + wtp->csw_sge.sop[0] = sge_dbg_reg->debug_T_Rx_SOP0_cnt; + wtp->csw_sge.sop[1] = sge_dbg_reg->debug_T_Rx_SOP1_cnt; + + wtp->csw_sge.eop[0] = sge_dbg_reg->debug_T_Rx_EOP0_cnt; + wtp->csw_sge.eop[1] = sge_dbg_reg->debug_T_Rx_EOP1_cnt; + + wtp->sge_pcie.sop[0] = sge_dbg_reg->debug_PD_Req_SOP0_cnt; + wtp->sge_pcie.sop[1] = sge_dbg_reg->debug_PD_Req_SOP1_cnt; + wtp->sge_pcie.sop[2] = sge_dbg_reg->debug_PD_Req_SOP2_cnt; + wtp->sge_pcie.sop[3] = sge_dbg_reg->debug_PD_Req_SOP3_cnt; + + wtp->sge_pcie.eop[0] = sge_dbg_reg->debug_PD_Req_EOP0_cnt; + wtp->sge_pcie.eop[1] = sge_dbg_reg->debug_PD_Req_EOP1_cnt; + wtp->sge_pcie.eop[2] = sge_dbg_reg->debug_PD_Req_EOP2_cnt; + wtp->sge_pcie.eop[3] = sge_dbg_reg->debug_PD_Req_EOP3_cnt; + + wtp->sge_pcie_ints.sop[0] = sge_dbg_reg->debug_PD_Req_Int0_cnt; + wtp->sge_pcie_ints.sop[1] = sge_dbg_reg->debug_PD_Req_Int1_cnt; + wtp->sge_pcie_ints.sop[2] = sge_dbg_reg->debug_PD_Req_Int2_cnt; + wtp->sge_pcie_ints.sop[3] = sge_dbg_reg->debug_PD_Req_Int3_cnt; + /* NO EOP, so fake it.*/ + wtp->sge_pcie_ints.eop[0] = sge_dbg_reg->debug_PD_Req_Int0_cnt; + wtp->sge_pcie_ints.eop[1] = sge_dbg_reg->debug_PD_Req_Int1_cnt; + wtp->sge_pcie_ints.eop[2] = sge_dbg_reg->debug_PD_Req_Int2_cnt; + wtp->sge_pcie_ints.eop[3] = sge_dbg_reg->debug_PD_Req_Int3_cnt; + + /*Get PCIE DMA1 STAT2*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, A_PCIE_T5_DMA_STAT2 + (i * 0x10)); + wtp->pcie_dma1_stat2.sop[i] = ((value >> 8) & 0x0F); + wtp->pcie_dma1_stat2.eop[i] = ((value >> 8) & 0x0F); + wtp->pcie_dma1_stat2_core.sop[i] += value & 0x0F; + wtp->pcie_dma1_stat2_core.eop[i] += value & 0x0F; + } + + /* Get mac porrx aFramesTransmittedok*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, 0x30a88 + ((i * 4) << 12)); + wtp->mac_porrx_aframestra_ok.sop[i] = (value & 0xFF); + wtp->mac_porrx_aframestra_ok.eop[i] = (value & 0xFF); + } + + /*Get SGE debug data high index 7*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_7); + wtp->sge_debug_data_high_indx7.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[0] = ((value >> 0) & 0x0F); + wtp->sge_debug_data_high_indx7.sop[1] = ((value >> 12) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[1] = ((value >> 8) & 0x0F); + wtp->sge_debug_data_high_indx7.sop[2] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[2] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_indx7.sop[3] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[3] = ((value >> 24) & 0x0F); + + /*Get SGE debug data high index 1*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_1); + wtp->sge_debug_data_high_indx1.sop[0] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_indx1.eop[0] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_indx1.sop[1] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_indx1.eop[1] = ((value >> 24) & 0x0F); + + /*Get TP debug CSIDE Tx registers*/ + for (i = 0; i < 2; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_CSIDE_TX0 + i), + true); + + wtp->utx_tpcside_tx.sop[i] = ((value >> 28) & 0xF);/*bits 28:31 + */ + wtp->utx_tpcside_tx.eop[i] = ((value >> 24) & 0xF); + } + + /*Get SGE debug data high index 9*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_9); + wtp->sge_debug_data_high_indx9.sop[0] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_indx9.sop[1] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_indx9.eop[0] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_indx9.eop[1] = ((value >> 24) & 0x0F); + wtp->sge_work_req_pkt.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_work_req_pkt.sop[1] = ((value >> 12) & 0x0F); + + /*Get LE DB response count*/ + value = t4_read_reg(padap, A_LE_DB_REQ_RSP_CNT); + wtp->le_db_rsp_cnt.sop = value & 0xF; + wtp->le_db_rsp_cnt.eop = (value >> 16) & 0xF; + + /*Get TP debug Eside PKTx*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_ESIDE_PKT0 + i), + true); + + wtp->tp_dbg_eside_pktx.sop[i] = ((value >> 12) & 0xF); + wtp->tp_dbg_eside_pktx.eop[i] = ((value >> 8) & 0xF); + } + + /* Get data responses from core to PCIE*/ + value = t4_read_reg(padap, A_PCIE_DMAW_SOP_CNT); + + wtp->pcie_core_dmaw.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dmaw.sop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dmaw.sop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dmaw.sop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + value = t4_read_reg(padap, A_PCIE_DMAW_EOP_CNT); + + wtp->pcie_core_dmaw.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dmaw.eop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dmaw.eop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dmaw.eop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + value = t4_read_reg(padap, A_PCIE_DMAI_CNT); + + wtp->pcie_core_dmai.sop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dmai.sop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dmai.sop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dmai.sop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + /* no eop for interrups, just fake it.*/ + wtp->pcie_core_dmai.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->pcie_core_dmai.eop[1] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->pcie_core_dmai.eop[2] = ((value >> 16) & 0xFF); /*bit 16:23*/ + wtp->pcie_core_dmai.eop[3] = ((value >> 24) & 0xFF); /*bit 24:31*/ + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +static int t6_wtp_data(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + struct sge_debug_reg_data *sge_dbg_reg = NULL; + struct cudbg_buffer scratch_buff; + struct tp_mib_data *ptp_mib = NULL; + struct wtp_data *wtp; + u32 Sge_Dbg[32] = {0}; + u32 value = 0; + u32 i = 0; + u32 drop = 0; + u32 err = 0; + u32 offset; + int rc = 0; + + rc = get_scratch_buff(dbg_buff, sizeof(struct wtp_data), &scratch_buff); + + if (rc) + goto err; + + offset = scratch_buff.offset; + wtp = (struct wtp_data *)((char *)scratch_buff.data + offset); + + read_sge_debug_data(pdbg_init, Sge_Dbg); + read_tp_mib_data(pdbg_init, &ptp_mib); + + sge_dbg_reg = (struct sge_debug_reg_data *) &Sge_Dbg[0]; + + /*# TX PATH*/ + + /*PCIE CMD STAT2*/ + value = t4_read_reg(padap, A_PCIE_T5_CMD_STAT2); + wtp->pcie_cmd_stat2.sop[0] = value & 0xFF; + wtp->pcie_cmd_stat2.eop[0] = value & 0xFF; + + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_7); + wtp->sge_pcie_cmd_req.sop[0] = ((value >> 20) & 0x0F); + wtp->sge_pcie_cmd_req.eop[0] = ((value >> 16) & 0x0F); + wtp->sge_pcie_cmd_req.sop[1] = ((value >> 28) & 0x0F); + wtp->sge_pcie_cmd_req.eop[1] = ((value >> 24) & 0x0F); + + value = t4_read_reg(padap, A_PCIE_T5_CMD_STAT3); + wtp->pcie_cmd_stat3.sop[0] = value & 0xFF; + wtp->pcie_cmd_stat3.eop[0] = value & 0xFF; + + /*Get command Resposes from PCIE to SGE*/ + wtp->pcie_sge_cmd_rsp.sop[0] = sge_dbg_reg->debug_PC_Rsp_SOP0_cnt; + wtp->pcie_sge_cmd_rsp.eop[0] = sge_dbg_reg->debug_PC_Rsp_EOP0_cnt; + wtp->pcie_sge_cmd_rsp.sop[1] = sge_dbg_reg->debug_PC_Rsp_SOP1_cnt; + wtp->pcie_sge_cmd_rsp.eop[1] = sge_dbg_reg->debug_PC_Rsp_EOP0_cnt; + + /* Get commands sent from SGE to CIM/uP*/ + wtp->sge_cim.sop[0] = sge_dbg_reg->debug_CIM_SOP0_cnt; + wtp->sge_cim.sop[1] = sge_dbg_reg->debug_CIM_SOP1_cnt; + + wtp->sge_cim.eop[0] = sge_dbg_reg->debug_CIM_EOP0_cnt; + wtp->sge_cim.eop[1] = sge_dbg_reg->debug_CIM_EOP1_cnt; + + /*Get SGE debug data high index 9*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_9); + wtp->sge_work_req_pkt.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_work_req_pkt.eop[0] = ((value >> 0) & 0x0F); + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, A_PCIE_T5_DMA_STAT2 + (i * 0x10)); + wtp->pcie_dma1_stat2.sop[i] = ((value >> 8) & 0x0F); + wtp->pcie_dma1_stat2.eop[i] = ((value >> 8) & 0x0F); + wtp->pcie_dma1_stat2_core.sop[i] = value & 0x0F; + wtp->pcie_dma1_stat2_core.eop[i] = value & 0x0F; + } + + /* Get DMA0 stats3*/ + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, A_PCIE_T5_DMA_STAT3 + (i * 0x10)); + wtp->pcie_t5_dma_stat3.sop[i] = value & 0xFF; + wtp->pcie_t5_dma_stat3.eop[i] = ((value >> 16) & 0xFF); + } + + /* Get ULP SE CNT CHx*/ + for (i = 0; i < 4; i++) { + value = t4_read_reg(padap, A_ULP_TX_SE_CNT_CH0 + (i * 4)); + wtp->ulp_se_cnt_chx.sop[i] = ((value >> 28) & 0x0F); + wtp->ulp_se_cnt_chx.eop[i] = ((value >> 24) & 0x0F); + } + + /* Get TP_DBG_CSIDE registers*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_CSIDE_RX0 + i), + true); + + wtp->utx_tpcside.sop[i] = ((value >> 28) & 0xF);/*bits 28:31*/ + wtp->utx_tpcside.eop[i] = ((value >> 24) & 0xF);/*bits 24:27*/ + wtp->tpcside_rxarb.sop[i] = ((value >> 12) & 0xF);/*bits 12:15*/ + wtp->tpcside_rxarb.eop[i] = ((value >> 8) & 0xF); /*bits 8:11*/ + } + + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_ESIDE_PKT0 + i), + true); + + + wtp->tpeside_mps.sop[i] = ((value >> 28) & 0xF); /*bits 28:31*/ + wtp->tpeside_mps.eop[i] = ((value >> 24) & 0xF); /*bits 24:27*/ + } + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_TX_SE_CNT_TP01 + (i << 2))); + wtp->tp_mps.sop[(i*2)] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->tp_mps.eop[(i*2)] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->tp_mps.sop[(i*2) + 1] = ((value >> 24) & 0xFF);/*bit 24:31 + */ + wtp->tp_mps.eop[(i*2) + 1] = ((value >> 16) & 0xFF);/*bit 16:23 + */ + } + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_TX_SE_CNT_MAC01 + (i << 2))); + wtp->mps_xgm.sop[(i*2)] = ((value >> 8) & 0xFF);/*bit 8:15*/ + wtp->mps_xgm.eop[(i*2)] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->mps_xgm.sop[(i*2) + 1] = ((value >> 24) & 0xFF);/*bit 24:31 + */ + wtp->mps_xgm.eop[(i*2) + 1] = ((value >> 16) & 0xFF);/*bit 16:23 + */ + } + + /* Get MAC PORTx PKT COUNT*/ + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, 0x3081c + ((i * 4) << 12)); + wtp->mac_portx_pkt_count.sop[i] = ((value >> 24) & 0xFF); + wtp->mac_portx_pkt_count.eop[i] = ((value >> 16) & 0xFF); + wtp->mac_porrx_pkt_count.sop[i] = ((value >> 8) & 0xFF); + wtp->mac_porrx_pkt_count.eop[i] = ((value >> 0) & 0xFF); + } + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, 0x30f20 + ((i * 4) << 12)); + wtp->mac_portx_aframestra_ok.sop[i] = value & 0xff; + wtp->mac_portx_aframestra_ok.eop[i] = value & 0xff; + } + + /*MAC_PORT_MTIP_1G10G_TX_etherStatsPkts*/ + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, 0x30f60 + ((i * 4) << 12)); + wtp->mac_portx_etherstatspkts.sop[i] = value & 0xff; + wtp->mac_portx_etherstatspkts.eop[i] = value & 0xff; + } + + /*RX path*/ + + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_7); + wtp->sge_debug_data_high_indx7.sop[0] = ((value >> 4) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[0] = ((value >> 0) & 0x0F); + wtp->sge_debug_data_high_indx7.sop[1] = ((value >> 12) & 0x0F); + wtp->sge_debug_data_high_indx7.eop[1] = ((value >> 8) & 0x0F); + + /*Get SGE debug data high index 1*/ + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_1); + wtp->sge_debug_data_high_indx1.sop[0] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_indx1.eop[0] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_indx1.sop[1] = ((value >> 28) & 0x0F); + wtp->sge_debug_data_high_indx1.eop[1] = ((value >> 24) & 0x0F); + + value = t4_read_reg(padap, A_SGE_DEBUG_DATA_HIGH_INDEX_9); + wtp->sge_debug_data_high_indx9.sop[0] = ((value >> 20) & 0x0F); + wtp->sge_debug_data_high_indx9.sop[1] = ((value >> 28) & 0x0F); + + wtp->sge_debug_data_high_indx9.eop[0] = ((value >> 16) & 0x0F); + wtp->sge_debug_data_high_indx9.eop[1] = ((value >> 24) & 0x0F); + + for (i = 0; i < 2; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_CSIDE_TX0 + i), + true); + + wtp->utx_tpcside_tx.sop[i] = ((value >> 28) & 0xF);/*bits 28:31 + */ + wtp->utx_tpcside_tx.eop[i] = ((value >> 24) & 0xF); + } + + /*ULP_RX input/output*/ + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_ULP_RX_SE_CNT_CH0 + (i*4))); + + wtp->pmrx_ulprx.sop[i] = ((value >> 4) & 0xF); /*bits 4:7*/ + wtp->pmrx_ulprx.eop[i] = ((value >> 0) & 0xF); /*bits 0:3*/ + wtp->ulprx_tpcside.sop[i] = ((value >> 28) & 0xF);/*bits 28:31*/ + wtp->ulprx_tpcside.eop[i] = ((value >> 24) & 0xF);/*bits 24:27*/ + } + + /*Get LE DB response count*/ + value = t4_read_reg(padap, A_LE_DB_REQ_RSP_CNT); + wtp->le_db_rsp_cnt.sop = value & 0xF; + wtp->le_db_rsp_cnt.eop = (value >> 16) & 0xF; + + /*Get TP debug Eside PKTx*/ + for (i = 0; i < 4; i++) { + t4_tp_pio_read(padap, &value, 1, (u32)(A_TP_DBG_ESIDE_PKT0 + i), + true); + + wtp->tp_dbg_eside_pktx.sop[i] = ((value >> 12) & 0xF); + wtp->tp_dbg_eside_pktx.eop[i] = ((value >> 8) & 0xF); + } + + drop = 0; + /*MPS_RX_SE_CNT_OUT01*/ + value = t4_read_reg(padap, (A_MPS_RX_SE_CNT_OUT01 + (i << 2))); + wtp->mps_tp.sop[0] = ((value >> 8) & 0xFF); /*bit 8:15*/ + wtp->mps_tp.eop[0] = ((value >> 0) & 0xFF); /*bit 0:7*/ + wtp->mps_tp.sop[1] = ((value >> 24) & 0xFF); /*bit 24:31*/ + wtp->mps_tp.eop[1] = ((value >> 16) & 0xFF); /*bit 16:23*/ + + drop = ptp_mib->TP_MIB_TNL_CNG_DROP_0.value; + drop += ptp_mib->TP_MIB_TNL_CNG_DROP_1.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_0.value; + drop += ptp_mib->TP_MIB_OFD_CHN_DROP_1.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_0.value; + drop += ptp_mib->TP_MIB_FCOE_DROP_1.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_0.value; + drop += ptp_mib->TP_MIB_OFD_VLN_DROP_1.value; + drop += ptp_mib->TP_MIB_USM_DROP.value; + + wtp->mps_tp.drops = drop; + + drop = 0; + for (i = 0; i < 8; i++) { + value = t4_read_reg(padap, (A_MPS_RX_SE_CNT_IN0 + (i << 2))); + + wtp->xgm_mps.sop[i] = ((value >> 8) & 0xFF); /*bits 8:15*/ + wtp->xgm_mps.eop[i] = ((value >> 0) & 0xFF); /*bits 0:7*/ + } + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, (A_MPS_RX_CLS_DROP_CNT0 + (i << 2))); + drop += (value & 0xFFFF) + ((value >> 16) & 0xFFFF); + } + wtp->xgm_mps.cls_drop = drop & 0xFF; + + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, 0x30e20 + ((i * 4) << 12)); + wtp->mac_porrx_aframestra_ok.sop[i] = value & 0xff; + wtp->mac_porrx_aframestra_ok.eop[i] = value & 0xff; + } + + /*MAC_PORT_MTIP_1G10G_RX_etherStatsPkts*/ + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, 0x30e60 + ((i * 4) << 12)); + wtp->mac_porrx_etherstatspkts.sop[i] = value & 0xff; + wtp->mac_porrx_etherstatspkts.eop[i] = value & 0xff; + } + + wtp->sge_pcie_ints.sop[0] = sge_dbg_reg->debug_PD_Req_Int0_cnt; + wtp->sge_pcie_ints.sop[1] = sge_dbg_reg->debug_PD_Req_Int1_cnt; + wtp->sge_pcie_ints.sop[2] = sge_dbg_reg->debug_PD_Req_Int2_cnt; + wtp->sge_pcie_ints.sop[3] = sge_dbg_reg->debug_PD_Req_Int3_cnt; + + /* Add up the overflow drops on all 4 ports.*/ + drop = 0; + for (i = 0; i < 2; i++) { + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 2))); + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_LB_DROP_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_DROP_FRAME_L + + (i << 2))); + + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_LB_TRUNC_FRAME_L + + (i << 3))); + drop += value; + value = t4_read_reg(padap, + (A_MPS_STAT_RX_BG_0_MAC_TRUNC_FRAME_L + + (i << 3))); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_LB_PORT_DROP_FRAMES) + + (i * T5_PORT_STRIDE))); + drop += value; + } + wtp->xgm_mps.drop = (drop & 0xFF); + + /* Add up the MPS errors that should result in dropped packets*/ + err = 0; + for (i = 0; i < 2; i++) { + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L) + + (i * T5_PORT_STRIDE) + 4)); + + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LESS_64B_L) + + (i * T5_PORT_STRIDE))); + err += value; + value = t4_read_reg(padap, + (T5_PORT0_REG(A_MPS_PORT_STAT_RX_PORT_LESS_64B_L) + + (i * T5_PORT_STRIDE) + 4)); + } + wtp->xgm_mps.err = (err & 0xFF); + + rc = write_compression_hdr(&scratch_buff, dbg_buff); + + if (rc) + goto err1; + + rc = compress_buff(&scratch_buff, dbg_buff); + +err1: + release_scratch_buff(&scratch_buff, dbg_buff); +err: + return rc; +} + +int collect_wtp_data(struct cudbg_init *pdbg_init, + struct cudbg_buffer *dbg_buff, + struct cudbg_error *cudbg_err) +{ + struct adapter *padap = pdbg_init->adap; + int rc = -1; + + if (is_t5(padap)) + rc = t5_wtp_data(pdbg_init, dbg_buff, cudbg_err); + else if (is_t6(padap)) + rc = t6_wtp_data(pdbg_init, dbg_buff, cudbg_err); + + return rc; +} Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/cudbg_wtp.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.c (revision 322022) @@ -0,0 +1,555 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include "osdep.h" +#include "fastlz.h" + +#if !defined(FASTLZ__COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) + +/* + * Always check for bound when decompressing. + * Generally it is best to leave it defined. + */ +#define FASTLZ_SAFE + +#if defined(WIN32) || defined(__NT__) || defined(_WIN32) || defined(__WIN32__) +#if defined(_MSC_VER) || defined(__GNUC__) +/* #include */ +#pragma warning(disable : 4242) +#pragma warning(disable : 4244) +#endif +#endif + +/* + * Give hints to the compiler for branch prediction optimization. + */ +#if defined(__GNUC__) && (__GNUC__ > 2) +#define FASTLZ_EXPECT_CONDITIONAL(c) (__builtin_expect((c), 1)) +#define FASTLZ_UNEXPECT_CONDITIONAL(c) (__builtin_expect((c), 0)) +#else +#define FASTLZ_EXPECT_CONDITIONAL(c) (c) +#define FASTLZ_UNEXPECT_CONDITIONAL(c) (c) +#endif + +/* + * Use inlined functions for supported systems. + */ +#if defined(__GNUC__) || defined(__DMC__) || defined(__POCC__) ||\ + defined(__WATCOMC__) || defined(__SUNPRO_C) +#define FASTLZ_INLINE inline +#elif defined(__BORLANDC__) || defined(_MSC_VER) || defined(__LCC__) +#define FASTLZ_INLINE __inline +#else +#define FASTLZ_INLINE +#endif + +/* + * Prevent accessing more than 8-bit at once, except on x86 architectures. + */ +#if !defined(FASTLZ_STRICT_ALIGN) +#define FASTLZ_STRICT_ALIGN +#if defined(__i386__) || defined(__386) /* GNU C, Sun Studio */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__i486__) || defined(__i586__) || defined(__i686__) /* GNU C */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(_M_IX86) /* Intel, MSVC */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__386) +#undef FASTLZ_STRICT_ALIGN +#elif defined(_X86_) /* MinGW */ +#undef FASTLZ_STRICT_ALIGN +#elif defined(__I86__) /* Digital Mars */ +#undef FASTLZ_STRICT_ALIGN +#endif +#endif + +/* + * FIXME: use preprocessor magic to set this on different platforms! + */ + +#define MAX_COPY 32 +#define MAX_LEN 264 /* 256 + 8 */ +#define MAX_DISTANCE 8192 + +#if !defined(FASTLZ_STRICT_ALIGN) +#define FASTLZ_READU16(p) (*((const unsigned short *)(p))) +#else +#define FASTLZ_READU16(p) ((p)[0] | (p)[1]<<8) +#endif + +#define HASH_LOG 13 +#define HASH_SIZE (1 << HASH_LOG) +#define HASH_MASK (HASH_SIZE - 1) +#define HASH_FUNCTION(v, p) {\ + v = FASTLZ_READU16(p);\ + v ^= FASTLZ_READU16(p + 1)^\ + (v>>(16 - HASH_LOG));\ + v &= HASH_MASK;\ + } + +#undef FASTLZ_LEVEL +#define FASTLZ_LEVEL 1 + +#undef FASTLZ_COMPRESSOR +#undef FASTLZ_DECOMPRESSOR +#define FASTLZ_COMPRESSOR fastlz1_compress +#define FASTLZ_DECOMPRESSOR fastlz1_decompress +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, + void *output); +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, + void *output, int maxout); +#include "fastlz.c" + +#undef FASTLZ_LEVEL +#define FASTLZ_LEVEL 2 + +#undef MAX_DISTANCE +#define MAX_DISTANCE 8191 +#define MAX_FARDISTANCE (65535 + MAX_DISTANCE - 1) + +#undef FASTLZ_COMPRESSOR +#undef FASTLZ_DECOMPRESSOR +#define FASTLZ_COMPRESSOR fastlz2_compress +#define FASTLZ_DECOMPRESSOR fastlz2_decompress +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, + void *output); +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, + void *output, int maxout); +#include "fastlz.c" + +int fastlz_compress(const void *input, int length, void *output) +{ + /* for short block, choose fastlz1 */ + if (length < 65536) + return fastlz1_compress(input, length, output); + + /* else... */ + return fastlz2_compress(input, length, output); +} + +int fastlz_decompress(const void *input, int length, void *output, int maxout) +{ + /* magic identifier for compression level */ + int level = ((*(const unsigned char *)input) >> 5) + 1; + + if (level == 1) + return fastlz1_decompress(input, length, output, maxout); + if (level == 2) + return fastlz2_decompress(input, length, output, maxout); + + /* unknown level, trigger error */ + return 0; +} + +int fastlz_compress_level(int level, const void *input, int length, + void *output) +{ + if (level == 1) + return fastlz1_compress(input, length, output); + if (level == 2) + return fastlz2_compress(input, length, output); + + return 0; +} + +#else /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ + + +static FASTLZ_INLINE int FASTLZ_COMPRESSOR(const void *input, int length, + void *output) +{ + const unsigned char *ip = (const unsigned char *) input; + const unsigned char *ip_bound = ip + length - 2; + const unsigned char *ip_limit = ip + length - 12; + unsigned char *op = (unsigned char *) output; + static const unsigned char *g_htab[HASH_SIZE]; + + const unsigned char **htab = g_htab; + const unsigned char **hslot; + unsigned int hval; + + unsigned int copy; + + /* sanity check */ + if (FASTLZ_UNEXPECT_CONDITIONAL(length < 4)) { + if (length) { + /* create literal copy only */ + *op++ = length - 1; + ip_bound++; + while (ip <= ip_bound) + *op++ = *ip++; + return length + 1; + } else + return 0; + } + + /* initializes hash table */ + for (hslot = htab; hslot < htab + HASH_SIZE; hslot++) + *hslot = ip; + + /* we start with literal copy */ + copy = 2; + *op++ = MAX_COPY - 1; + *op++ = *ip++; + *op++ = *ip++; + + /* main loop */ + while (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) { + const unsigned char *ref; + unsigned int distance; + + /* minimum match length */ + unsigned int len = 3; + + /* comparison starting-point */ + const unsigned char *anchor = ip; + + /* check for a run */ +#if FASTLZ_LEVEL == 2 + if (ip[0] == ip[-1] && + FASTLZ_READU16(ip - 1) == FASTLZ_READU16(ip + 1)) { + distance = 1; + ip += 3; + ref = anchor - 1 + 3; + goto match; + } +#endif + + /* find potential match */ + HASH_FUNCTION(hval, ip); + hslot = htab + hval; + ref = htab[hval]; + + /* calculate distance to the match */ + distance = anchor - ref; + + /* update hash table */ + *hslot = anchor; + + if (!ref) + goto literal; + /* is this a match? check the first 3 bytes */ + if (distance == 0 || +#if FASTLZ_LEVEL == 1 + (distance >= MAX_DISTANCE) || +#else + (distance >= MAX_FARDISTANCE) || +#endif + *ref++ != *ip++ || *ref++ != *ip++ || + *ref++ != *ip++) + goto literal; + +#if FASTLZ_LEVEL == 2 + /* far, needs at least 5-byte match */ + if (distance >= MAX_DISTANCE) { + if (*ip++ != *ref++ || *ip++ != *ref++) + goto literal; + len += 2; + } + +match: +#endif + + /* last matched byte */ + ip = anchor + len; + + /* distance is biased */ + distance--; + + if (!distance) { + /* zero distance means a run */ + unsigned char x = ip[-1]; + while (ip < ip_bound) + if (*ref++ != x) + break; + else + ip++; + } else + for (;;) { + /* safe because the outer check + * against ip limit */ + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + if (*ref++ != *ip++) + break; + while (ip < ip_bound) + if (*ref++ != *ip++) + break; + break; + } + + /* if we have copied something, adjust the copy count */ + if (copy) + /* copy is biased, '0' means 1 byte copy */ + *(op - copy - 1) = copy - 1; + else + /* back, to overwrite the copy count */ + op--; + + /* reset literal counter */ + copy = 0; + + /* length is biased, '1' means a match of 3 bytes */ + ip -= 3; + len = ip - anchor; + + /* encode the match */ +#if FASTLZ_LEVEL == 2 + if (distance < MAX_DISTANCE) { + if (len < 7) { + *op++ = (len << 5) + (distance >> 8); + *op++ = (distance & 255); + } else { + *op++ = (7 << 5) + (distance >> 8); + for (len -= 7; len >= 255; len -= 255) + *op++ = 255; + *op++ = len; + *op++ = (distance & 255); + } + } else { + /* far away, but not yet in the another galaxy... */ + if (len < 7) { + distance -= MAX_DISTANCE; + *op++ = (len << 5) + 31; + *op++ = 255; + *op++ = distance >> 8; + *op++ = distance & 255; + } else { + distance -= MAX_DISTANCE; + *op++ = (7 << 5) + 31; + for (len -= 7; len >= 255; len -= 255) + *op++ = 255; + *op++ = len; + *op++ = 255; + *op++ = distance >> 8; + *op++ = distance & 255; + } + } +#else + + if (FASTLZ_UNEXPECT_CONDITIONAL(len > MAX_LEN - 2)) + while (len > MAX_LEN - 2) { + *op++ = (7 << 5) + (distance >> 8); + *op++ = MAX_LEN - 2 - 7 - 2; + *op++ = (distance & 255); + len -= MAX_LEN - 2; + } + + if (len < 7) { + *op++ = (len << 5) + (distance >> 8); + *op++ = (distance & 255); + } else { + *op++ = (7 << 5) + (distance >> 8); + *op++ = len - 7; + *op++ = (distance & 255); + } +#endif + + /* update the hash at match boundary */ + HASH_FUNCTION(hval, ip); + htab[hval] = ip++; + HASH_FUNCTION(hval, ip); + htab[hval] = ip++; + + /* assuming literal copy */ + *op++ = MAX_COPY - 1; + + continue; + +literal: + *op++ = *anchor++; + ip = anchor; + copy++; + if (FASTLZ_UNEXPECT_CONDITIONAL(copy == MAX_COPY)) { + copy = 0; + *op++ = MAX_COPY - 1; + } + } + + /* left-over as literal copy */ + ip_bound++; + while (ip <= ip_bound) { + *op++ = *ip++; + copy++; + if (copy == MAX_COPY) { + copy = 0; + *op++ = MAX_COPY - 1; + } + } + + /* if we have copied something, adjust the copy length */ + if (copy) + *(op - copy - 1) = copy - 1; + else + op--; + +#if FASTLZ_LEVEL == 2 + /* marker for fastlz2 */ + *(unsigned char *)output |= (1 << 5); +#endif + + return op - (unsigned char *)output; +} + +static FASTLZ_INLINE int FASTLZ_DECOMPRESSOR(const void *input, int length, + void *output, int maxout) +{ + const unsigned char *ip = (const unsigned char *) input; + const unsigned char *ip_limit = ip + length; + unsigned char *op = (unsigned char *) output; + unsigned char *op_limit = op + maxout; + unsigned int ctrl = (*ip++) & 31; + int loop = 1; + + do { + const unsigned char *ref = op; + unsigned int len = ctrl >> 5; + unsigned int ofs = (ctrl & 31) << 8; + + if (ctrl >= 32) { +#if FASTLZ_LEVEL == 2 + unsigned char code; +#endif + len--; + ref -= ofs; + if (len == 7 - 1) +#if FASTLZ_LEVEL == 1 + len += *ip++; + ref -= *ip++; +#else + do { + code = *ip++; + len += code; + } while (code == 255); + code = *ip++; + ref -= code; + + /* match from 16-bit distance */ + if (FASTLZ_UNEXPECT_CONDITIONAL(code == 255)) + if (FASTLZ_EXPECT_CONDITIONAL(ofs == + (31 << 8))) { + ofs = (*ip++) << 8; + ofs += *ip++; + ref = op - ofs - MAX_DISTANCE; + } +#endif + +#ifdef FASTLZ_SAFE + if (FASTLZ_UNEXPECT_CONDITIONAL(op + len + 3 > + op_limit)) + return 0; + + if (FASTLZ_UNEXPECT_CONDITIONAL(ref - 1 < + (unsigned char *)output) + ) + return 0; +#endif + + if (FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit)) + ctrl = *ip++; + else + loop = 0; + + if (ref == op) { + /* optimize copy for a run */ + unsigned char b = ref[-1]; + *op++ = b; + *op++ = b; + *op++ = b; + for (; len; --len) + *op++ = b; + } else { +#if !defined(FASTLZ_STRICT_ALIGN) + const unsigned short *p; + unsigned short *q; +#endif + /* copy from reference */ + ref--; + *op++ = *ref++; + *op++ = *ref++; + *op++ = *ref++; + +#if !defined(FASTLZ_STRICT_ALIGN) + /* copy a byte, so that now it's word aligned */ + if (len & 1) { + *op++ = *ref++; + len--; + } + + /* copy 16-bit at once */ + q = (unsigned short *) op; + op += len; + p = (const unsigned short *) ref; + for (len >>= 1; len > 4; len -= 4) { + *q++ = *p++; + *q++ = *p++; + *q++ = *p++; + *q++ = *p++; + } + for (; len; --len) + *q++ = *p++; +#else + for (; len; --len) + *op++ = *ref++; +#endif + } + } else { + ctrl++; +#ifdef FASTLZ_SAFE + if (FASTLZ_UNEXPECT_CONDITIONAL(op + ctrl > op_limit)) + return 0; + if (FASTLZ_UNEXPECT_CONDITIONAL(ip + ctrl > ip_limit)) + return 0; +#endif + + *op++ = *ip++; + for (--ctrl; ctrl; ctrl--) + *op++ = *ip++; + + loop = FASTLZ_EXPECT_CONDITIONAL(ip < ip_limit); + if (loop) + ctrl = *ip++; + } + } while (FASTLZ_EXPECT_CONDITIONAL(loop)); + + return op - (unsigned char *)output; +} + +#endif /* !defined(FASTLZ_COMPRESSOR) && !defined(FASTLZ_DECOMPRESSOR) */ Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.h (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.h (revision 322022) @@ -0,0 +1,62 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + + $FreeBSD$ + */ +#ifndef FASTLZ_H +#define FASTLZ_H + +#define FASTLZ_VERSION 0x000100 + +#define FASTLZ_VERSION_MAJOR 0 +#define FASTLZ_VERSION_MINOR 0 +#define FASTLZ_VERSION_REVISION 0 + +#define FASTLZ_VERSION_STRING "0.1.0" + +struct cudbg_buffer; + +int fastlz_compress(const void *input, int length, void *output); +int fastlz_compress_level(int level, const void *input, int length, + void *output); +int fastlz_decompress(const void *input, int length, void *output, int maxout); + +/* prototypes */ + +int write_magic(struct cudbg_buffer *); +int detect_magic(struct cudbg_buffer *); + +int write_to_buf(void *, u32, u32 *, void *, u32); +int read_from_buf(void *, u32, u32 *, void *, u32); + +int write_chunk_header(struct cudbg_buffer *, int, int, unsigned long, + unsigned long, unsigned long); + +int read_chunk_header(struct cudbg_buffer *, int* , int*, unsigned long*, + unsigned long*, unsigned long*); + +unsigned long block_compress(const unsigned char *, unsigned long length, + unsigned char *); +#endif /* FASTLZ_H */ Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz.h ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz_api.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz_api.c (nonexistent) +++ projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz_api.c (revision 322022) @@ -0,0 +1,531 @@ +/* + FastLZ - lightning-fast lossless compression library + + Copyright (C) 2007 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2006 Ariya Hidayat (ariya@kde.org) + Copyright (C) 2005 Ariya Hidayat (ariya@kde.org) + + Permission is hereby granted, free of charge, to any person obtaining a copy + of this software and associated documentation files (the "Software"), to deal + in the Software without restriction, including without limitation the rights + to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + copies of the Software, and to permit persons to whom the Software is + furnished to do so, subject to the following conditions: + + The above copyright notice and this permission notice shall be included in + all copies or substantial portions of the Software. + + THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + THE SOFTWARE. + */ +#include +__FBSDID("$FreeBSD$"); + +#include "osdep.h" +#include "cudbg.h" +#include "cudbg_lib_common.h" +#include "fastlz.h" + +static unsigned char sixpack_magic[8] = {137, '6', 'P', 'K', 13, 10, 26, 10}; + +#define CUDBG_BLOCK_SIZE (63*1024) +#define CUDBG_CHUNK_BUF_LEN 16 +#define CUDBG_MIN_COMPR_LEN 32 /*min data length for applying compression*/ + +/* for Adler-32 checksum algorithm, see RFC 1950 Section 8.2 */ + +#define ADLER32_BASE 65521 + +static inline unsigned long update_adler32(unsigned long checksum, + const void *buf, int len) +{ + const unsigned char *ptr = (const unsigned char *)buf; + unsigned long s1 = checksum & 0xffff; + unsigned long s2 = (checksum >> 16) & 0xffff; + + while (len > 0) { + unsigned k = len < 5552 ? len : 5552; + len -= k; + + while (k >= 8) { + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + s1 += *ptr++; s2 += s1; + k -= 8; + } + + while (k-- > 0) { + s1 += *ptr++; s2 += s1; + } + s1 = s1 % ADLER32_BASE; + s2 = s2 % ADLER32_BASE; + } + return (s2 << 16) + s1; +} + +int write_magic(struct cudbg_buffer *_out_buff) +{ + int rc; + + rc = write_to_buf(_out_buff->data, _out_buff->size, &_out_buff->offset, + sixpack_magic, 8); + + return rc; +} + +int write_to_buf(void *out_buf, u32 out_buf_size, u32 *offset, void *in_buf, + u32 in_buf_size) +{ + int rc = 0; + + if (*offset >= out_buf_size) { + rc = CUDBG_STATUS_OUTBUFF_OVERFLOW; + goto err; + } + + memcpy((char *)out_buf + *offset, in_buf, in_buf_size); + *offset = *offset + in_buf_size; + +err: + return rc; +} + +int read_from_buf(void *in_buf, u32 in_buf_size, u32 *offset, void *out_buf, + u32 out_buf_size) +{ + if (in_buf_size - *offset < out_buf_size) + return 0; + + memcpy((char *)out_buf, (char *)in_buf + *offset, out_buf_size); + *offset = *offset + out_buf_size; + return out_buf_size; +} + +int write_chunk_header(struct cudbg_buffer *_outbuf, int id, int options, + unsigned long size, unsigned long checksum, + unsigned long extra) +{ + unsigned char buffer[CUDBG_CHUNK_BUF_LEN]; + int rc = 0; + + buffer[0] = id & 255; + buffer[1] = (unsigned char)(id >> 8); + buffer[2] = options & 255; + buffer[3] = (unsigned char)(options >> 8); + buffer[4] = size & 255; + buffer[5] = (size >> 8) & 255; + buffer[6] = (size >> 16) & 255; + buffer[7] = (size >> 24) & 255; + buffer[8] = checksum & 255; + buffer[9] = (checksum >> 8) & 255; + buffer[10] = (checksum >> 16) & 255; + buffer[11] = (checksum >> 24) & 255; + buffer[12] = extra & 255; + buffer[13] = (extra >> 8) & 255; + buffer[14] = (extra >> 16) & 255; + buffer[15] = (extra >> 24) & 255; + + rc = write_to_buf(_outbuf->data, _outbuf->size, &_outbuf->offset, + buffer, 16); + + return rc; +} + +int write_compression_hdr(struct cudbg_buffer *pin_buff, + struct cudbg_buffer *pout_buff) +{ + struct cudbg_buffer tmp_buffer; + unsigned long fsize = pin_buff->size; + unsigned char *buffer; + unsigned long checksum; + int rc; + char *shown_name = "abc"; + + /* Always release inner scratch buffer, before releasing outer. */ + rc = get_scratch_buff(pout_buff, 10, &tmp_buffer); + + if (rc) + goto err; + + buffer = (unsigned char *)tmp_buffer.data; + + rc = write_magic(pout_buff); + + if (rc) + goto err1; + + /* chunk for File Entry */ + buffer[0] = fsize & 255; + buffer[1] = (fsize >> 8) & 255; + buffer[2] = (fsize >> 16) & 255; + buffer[3] = (fsize >> 24) & 255; + buffer[4] = 0; + buffer[5] = 0; + buffer[6] = 0; + buffer[7] = 0; + buffer[8] = (strlen(shown_name)+1) & 255; + buffer[9] = (unsigned char)((strlen(shown_name)+1) >> 8); + checksum = 1L; + checksum = update_adler32(checksum, buffer, 10); + checksum = update_adler32(checksum, shown_name, + (int)strlen(shown_name)+1); + + rc = write_chunk_header(pout_buff, 1, 0, + 10+(unsigned long)strlen(shown_name)+1, + checksum, 0); + + if (rc) + goto err1; + + rc = write_to_buf(pout_buff->data, pout_buff->size, + &(pout_buff->offset), buffer, 10); + + if (rc) + goto err1; + + rc = write_to_buf(pout_buff->data, pout_buff->size, + &(pout_buff->offset), shown_name, + (u32)strlen(shown_name)+1); + + if (rc) + goto err1; + +err1: + release_scratch_buff(&tmp_buffer, pout_buff); +err: + return rc; +} + +int compress_buff(struct cudbg_buffer *pin_buff, struct cudbg_buffer *pout_buff) +{ + struct cudbg_buffer tmp_buffer; + struct cudbg_hdr *cudbg_hdr; + unsigned long checksum; + unsigned char *result; + unsigned int bytes_read; + int chunk_size, level = 2, rc = 0; + int compress_method = 1; + + bytes_read = pin_buff->size; + rc = get_scratch_buff(pout_buff, CUDBG_BLOCK_SIZE, &tmp_buffer); + + if (rc) + goto err; + + result = (unsigned char *)tmp_buffer.data; + + if (bytes_read < 32) + compress_method = 0; + + cudbg_hdr = (struct cudbg_hdr *) pout_buff->data; + + switch (compress_method) { + case 1: + chunk_size = fastlz_compress_level(level, pin_buff->data, + bytes_read, result); + + checksum = update_adler32(1L, result, chunk_size); + + if ((chunk_size > 62000) && (cudbg_hdr->reserved[7] < (u32) + chunk_size)) /* 64512 */ + cudbg_hdr->reserved[7] = (u32) chunk_size; + + rc = write_chunk_header(pout_buff, 17, 1, chunk_size, checksum, + bytes_read); + + if (rc) + goto err_put_buff; + + rc = write_to_buf(pout_buff->data, pout_buff->size, + &pout_buff->offset, result, chunk_size); + + if (rc) + goto err_put_buff; + + break; + + /* uncompressed, also fallback method */ + case 0: + default: + checksum = update_adler32(1L, pin_buff->data, bytes_read); + + rc = write_chunk_header(pout_buff, 17, 0, bytes_read, checksum, + bytes_read); + + if (rc) + goto err_put_buff; + + rc = write_to_buf(pout_buff->data, pout_buff->size, + &pout_buff->offset, pin_buff->data, + bytes_read); + if (rc) + goto err_put_buff; + + break; + } + +err_put_buff: + release_scratch_buff(&tmp_buffer, pout_buff); +err: + return rc; +} + +/* return non-zero if magic sequence is detected */ +/* warning: reset the read pointer to the beginning of the file */ +int detect_magic(struct cudbg_buffer *_c_buff) +{ + unsigned char buffer[8]; + size_t bytes_read; + int c; + + bytes_read = read_from_buf(_c_buff->data, _c_buff->size, + &_c_buff->offset, buffer, 8); + + if (bytes_read < 8) + return 0; + + for (c = 0; c < 8; c++) + if (buffer[c] != sixpack_magic[c]) + return 0; + + return -1; +} + +static inline unsigned long readU16(const unsigned char *ptr) +{ + return ptr[0]+(ptr[1]<<8); +} + +static inline unsigned long readU32(const unsigned char *ptr) +{ + return ptr[0]+(ptr[1]<<8)+(ptr[2]<<16)+(ptr[3]<<24); +} + +int read_chunk_header(struct cudbg_buffer *pc_buff, int *pid, int *poptions, + unsigned long *psize, unsigned long *pchecksum, + unsigned long *pextra) +{ + unsigned char buffer[CUDBG_CHUNK_BUF_LEN]; + int byte_r = read_from_buf(pc_buff->data, pc_buff->size, + &pc_buff->offset, buffer, 16); + if (byte_r == 0) + return 0; + + *pid = readU16(buffer) & 0xffff; + *poptions = readU16(buffer+2) & 0xffff; + *psize = readU32(buffer+4) & 0xffffffff; + *pchecksum = readU32(buffer+8) & 0xffffffff; + *pextra = readU32(buffer+12) & 0xffffffff; + return 0; +} + +int validate_buffer(struct cudbg_buffer *compressed_buffer) +{ + if (!detect_magic(compressed_buffer)) + return CUDBG_STATUS_INVALID_BUFF; + + return 0; +} + +int decompress_buffer(struct cudbg_buffer *pc_buff, + struct cudbg_buffer *pd_buff) +{ + struct cudbg_buffer tmp_compressed_buffer; + struct cudbg_buffer tmp_decompressed_buffer; + unsigned char *compressed_buffer; + unsigned char *decompressed_buffer; + unsigned char buffer[CUDBG_MIN_COMPR_LEN]; + unsigned long chunk_size; + unsigned long chunk_checksum; + unsigned long chunk_extra; + unsigned long checksum; + unsigned long total_extracted = 0; + unsigned long r; + unsigned long remaining; + unsigned long bytes_read; + u32 decompressed_size = 0; + int chunk_id, chunk_options, rc; + + if (pd_buff->size < 2 * CUDBG_BLOCK_SIZE) + return CUDBG_STATUS_SMALL_BUFF; + + rc = get_scratch_buff(pd_buff, CUDBG_BLOCK_SIZE, + &tmp_compressed_buffer); + + if (rc) + goto err_cbuff; + + rc = get_scratch_buff(pd_buff, CUDBG_BLOCK_SIZE, + &tmp_decompressed_buffer); + if (rc) + goto err_dcbuff; + + compressed_buffer = (unsigned char *)tmp_compressed_buffer.data; + decompressed_buffer = (unsigned char *)tmp_decompressed_buffer.data; + + /* main loop */ + + for (;;) { + if (pc_buff->offset > pc_buff->size) + break; + + rc = read_chunk_header(pc_buff, &chunk_id, &chunk_options, + &chunk_size, &chunk_checksum, + &chunk_extra); + if (rc != 0) + break; + + /* skip 8+16 */ + if ((chunk_id == 1) && (chunk_size > 10) && + (chunk_size < CUDBG_BLOCK_SIZE)) { + + bytes_read = read_from_buf(pc_buff->data, pc_buff->size, + &pc_buff->offset, buffer, + chunk_size); + + if (bytes_read == 0) + return 0; + + checksum = update_adler32(1L, buffer, chunk_size); + if (checksum != chunk_checksum) + return CUDBG_STATUS_CHKSUM_MISSMATCH; + + decompressed_size = (u32)readU32(buffer); + + if (pd_buff->size < decompressed_size) { + + pd_buff->size = 2 * CUDBG_BLOCK_SIZE + + decompressed_size; + pc_buff->offset -= chunk_size + 16; + return CUDBG_STATUS_SMALL_BUFF; + } + total_extracted = 0; + + } + + if (chunk_size > CUDBG_BLOCK_SIZE) { + /* Release old allocated memory */ + release_scratch_buff(&tmp_decompressed_buffer, pd_buff); + release_scratch_buff(&tmp_compressed_buffer, pd_buff); + + /* allocate new memory with chunk_size size */ + rc = get_scratch_buff(pd_buff, chunk_size, + &tmp_compressed_buffer); + if (rc) + goto err_cbuff; + + rc = get_scratch_buff(pd_buff, chunk_size, + &tmp_decompressed_buffer); + if (rc) + goto err_dcbuff; + + compressed_buffer = (unsigned char *)tmp_compressed_buffer.data; + decompressed_buffer = (unsigned char *)tmp_decompressed_buffer.data; + } + + if ((chunk_id == 17) && decompressed_size) { + /* uncompressed */ + switch (chunk_options) { + /* stored, simply copy to output */ + case 0: + total_extracted += chunk_size; + remaining = chunk_size; + checksum = 1L; + for (;;) { + /* Write a funtion for this */ + r = (CUDBG_BLOCK_SIZE < remaining) ? + CUDBG_BLOCK_SIZE : remaining; + bytes_read = + read_from_buf(pc_buff->data, + pc_buff->size, + &pc_buff->offset, buffer, + r); + + if (bytes_read == 0) + return 0; + + write_to_buf(pd_buff->data, + pd_buff->size, + &pd_buff->offset, buffer, + bytes_read); + checksum = update_adler32(checksum, + buffer, + bytes_read); + remaining -= bytes_read; + + /* verify everything is written + * correctly */ + if (checksum != chunk_checksum) + return + CUDBG_STATUS_CHKSUM_MISSMATCH; + } + + break; + + /* compressed using FastLZ */ + case 1: + bytes_read = read_from_buf(pc_buff->data, + pc_buff->size, + &pc_buff->offset, + compressed_buffer, + chunk_size); + + if (bytes_read == 0) + return 0; + + checksum = update_adler32(1L, compressed_buffer, + chunk_size); + total_extracted += chunk_extra; + + /* verify that the chunk data is correct */ + if (checksum != chunk_checksum) { + return CUDBG_STATUS_CHKSUM_MISSMATCH; + } else { + /* decompress and verify */ + remaining = + fastlz_decompress(compressed_buffer, + chunk_size, + decompressed_buffer, + chunk_extra); + + if (remaining != chunk_extra) { + rc = + CUDBG_STATUS_DECOMPRESS_FAIL; + goto err; + } else { + write_to_buf(pd_buff->data, + pd_buff->size, + &pd_buff->offset, + decompressed_buffer, + chunk_extra); + } + } + break; + + default: + break; + } + + } + + } + +err: + release_scratch_buff(&tmp_decompressed_buffer, pd_buff); +err_dcbuff: + release_scratch_buff(&tmp_compressed_buffer, pd_buff); + +err_cbuff: + return rc; +} + Property changes on: projects/make-check-sandbox/sys/dev/cxgbe/cudbg/fastlz_api.c ___________________________________________________________________ Added: svn:eol-style ## -0,0 +1 ## +native \ No newline at end of property Added: svn:keywords ## -0,0 +1 ## +FreeBSD=%H \ No newline at end of property Added: svn:mime-type ## -0,0 +1 ## +text/plain \ No newline at end of property Index: projects/make-check-sandbox/sys/dev/cxgbe/t4_ioctl.h =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/t4_ioctl.h (revision 322021) +++ projects/make-check-sandbox/sys/dev/cxgbe/t4_ioctl.h (revision 322022) @@ -1,360 +1,369 @@ /*- * Copyright (c) 2011 Chelsio Communications, Inc. * All rights reserved. * Written by: Navdeep Parhar * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * $FreeBSD$ * */ #ifndef __T4_IOCTL_H__ #define __T4_IOCTL_H__ #include #include /* * Ioctl commands specific to this driver. */ enum { T4_GETREG = 0x40, /* read register */ T4_SETREG, /* write register */ T4_REGDUMP, /* dump of all registers */ T4_GET_FILTER_MODE, /* get global filter mode */ T4_SET_FILTER_MODE, /* set global filter mode */ T4_GET_FILTER, /* get information about a filter */ T4_SET_FILTER, /* program a filter */ T4_DEL_FILTER, /* delete a filter */ T4_GET_SGE_CONTEXT, /* get SGE context for a queue */ T4_LOAD_FW, /* flash firmware */ T4_GET_MEM, /* read memory */ T4_GET_I2C, /* read from i2c addressible device */ T4_CLEAR_STATS, /* clear a port's MAC statistics */ T4_SET_OFLD_POLICY, /* Set offload policy */ T4_SET_SCHED_CLASS, /* set sched class */ T4_SET_SCHED_QUEUE, /* set queue class */ T4_GET_TRACER, /* get information about a tracer */ T4_SET_TRACER, /* program a tracer */ T4_LOAD_CFG, /* copy a config file to card's flash */ T4_LOAD_BOOT, /* flash boot rom */ T4_LOAD_BOOTCFG, /* flash bootcfg */ + T4_CUDBG_DUMP, /* debug dump of chip state */ }; struct t4_reg { uint32_t addr; uint32_t size; uint64_t val; }; #define T4_REGDUMP_SIZE (160 * 1024) #define T5_REGDUMP_SIZE (332 * 1024) struct t4_regdump { uint32_t version; uint32_t len; /* bytes */ uint32_t *data; }; struct t4_data { uint32_t len; uint8_t *data; }; struct t4_bootrom { uint32_t pf_offset; uint32_t pfidx_addr; uint32_t len; uint8_t *data; }; struct t4_i2c_data { uint8_t port_id; uint8_t dev_addr; uint8_t offset; uint8_t len; uint8_t data[8]; }; /* * A hardware filter is some valid combination of these. */ #define T4_FILTER_IPv4 0x1 /* IPv4 packet */ #define T4_FILTER_IPv6 0x2 /* IPv6 packet */ #define T4_FILTER_IP_SADDR 0x4 /* Source IP address or network */ #define T4_FILTER_IP_DADDR 0x8 /* Destination IP address or network */ #define T4_FILTER_IP_SPORT 0x10 /* Source IP port */ #define T4_FILTER_IP_DPORT 0x20 /* Destination IP port */ #define T4_FILTER_FCoE 0x40 /* Fibre Channel over Ethernet packet */ #define T4_FILTER_PORT 0x80 /* Physical ingress port */ #define T4_FILTER_VNIC 0x100 /* VNIC id or outer VLAN */ #define T4_FILTER_VLAN 0x200 /* VLAN ID */ #define T4_FILTER_IP_TOS 0x400 /* IPv4 TOS/IPv6 Traffic Class */ #define T4_FILTER_IP_PROTO 0x800 /* IP protocol */ #define T4_FILTER_ETH_TYPE 0x1000 /* Ethernet Type */ #define T4_FILTER_MAC_IDX 0x2000 /* MPS MAC address match index */ #define T4_FILTER_MPS_HIT_TYPE 0x4000 /* MPS match type */ #define T4_FILTER_IP_FRAGMENT 0x8000 /* IP fragment */ #define T4_FILTER_IC_VNIC 0x80000000 /* TP Ingress Config's F_VNIC bit. It indicates whether T4_FILTER_VNIC bit means VNIC id (PF/VF) or outer VLAN. 0 = oVLAN, 1 = VNIC */ /* Filter action */ enum { FILTER_PASS = 0, /* default */ FILTER_DROP, FILTER_SWITCH }; /* 802.1q manipulation on FILTER_SWITCH */ enum { VLAN_NOCHANGE = 0, /* default */ VLAN_REMOVE, VLAN_INSERT, VLAN_REWRITE }; /* MPS match type */ enum { UCAST_EXACT = 0, /* exact unicast match */ UCAST_HASH = 1, /* inexact (hashed) unicast match */ MCAST_EXACT = 2, /* exact multicast match */ MCAST_HASH = 3, /* inexact (hashed) multicast match */ PROMISC = 4, /* no match but port is promiscuous */ HYPPROMISC = 5, /* port is hypervisor-promisuous + not bcast */ BCAST = 6, /* broadcast packet */ }; /* Rx steering */ enum { DST_MODE_QUEUE, /* queue is directly specified by filter */ DST_MODE_RSS_QUEUE, /* filter specifies RSS entry containing queue */ DST_MODE_RSS, /* queue selected by default RSS hash lookup */ DST_MODE_FILT_RSS /* queue selected by hashing in filter-specified RSS subtable */ }; struct t4_filter_tuple { /* * These are always available. */ uint8_t sip[16]; /* source IP address (IPv4 in [3:0]) */ uint8_t dip[16]; /* destinatin IP address (IPv4 in [3:0]) */ uint16_t sport; /* source port */ uint16_t dport; /* destination port */ /* * A combination of these (up to 36 bits) is available. TP_VLAN_PRI_MAP * is used to select the global mode and all filters are limited to the * set of fields allowed by the global mode. */ uint16_t vnic; /* VNIC id (PF/VF) or outer VLAN tag */ uint16_t vlan; /* VLAN tag */ uint16_t ethtype; /* Ethernet type */ uint8_t tos; /* TOS/Traffic Type */ uint8_t proto; /* protocol type */ uint32_t fcoe:1; /* FCoE packet */ uint32_t iport:3; /* ingress port */ uint32_t matchtype:3; /* MPS match type */ uint32_t frag:1; /* fragmentation extension header */ uint32_t macidx:9; /* exact match MAC index */ uint32_t vlan_vld:1; /* VLAN valid */ uint32_t ovlan_vld:1; /* outer VLAN tag valid, value in "vnic" */ uint32_t pfvf_vld:1; /* VNIC id (PF/VF) valid, value in "vnic" */ }; struct t4_filter_specification { uint32_t hitcnts:1; /* count filter hits in TCB */ uint32_t prio:1; /* filter has priority over active/server */ uint32_t type:1; /* 0 => IPv4, 1 => IPv6 */ uint32_t action:2; /* drop, pass, switch */ uint32_t rpttid:1; /* report TID in RSS hash field */ uint32_t dirsteer:1; /* 0 => RSS, 1 => steer to iq */ uint32_t iq:10; /* ingress queue */ uint32_t maskhash:1; /* dirsteer=0: store RSS hash in TCB */ uint32_t dirsteerhash:1;/* dirsteer=1: 0 => TCB contains RSS hash */ /* 1 => TCB contains IQ ID */ /* * Switch proxy/rewrite fields. An ingress packet which matches a * filter with "switch" set will be looped back out as an egress * packet -- potentially with some Ethernet header rewriting. */ uint32_t eport:2; /* egress port to switch packet out */ uint32_t newdmac:1; /* rewrite destination MAC address */ uint32_t newsmac:1; /* rewrite source MAC address */ uint32_t newvlan:2; /* rewrite VLAN Tag */ uint8_t dmac[ETHER_ADDR_LEN]; /* new destination MAC address */ uint8_t smac[ETHER_ADDR_LEN]; /* new source MAC address */ uint16_t vlan; /* VLAN Tag to insert */ /* * Filter rule value/mask pairs. */ struct t4_filter_tuple val; struct t4_filter_tuple mask; }; struct t4_filter { uint32_t idx; uint16_t l2tidx; uint16_t smtidx; uint64_t hits; struct t4_filter_specification fs; }; /* Tx Scheduling Class parameters */ struct t4_sched_class_params { int8_t level; /* scheduler hierarchy level */ int8_t mode; /* per-class or per-flow */ int8_t rateunit; /* bit or packet rate */ int8_t ratemode; /* %port relative or kbps absolute */ int8_t channel; /* scheduler channel [0..N] */ int8_t cl; /* scheduler class [0..N] */ int32_t minrate; /* minimum rate */ int32_t maxrate; /* maximum rate */ int16_t weight; /* percent weight */ int16_t pktsize; /* average packet size */ }; /* * Support for "sched-class" command to allow a TX Scheduling Class to be * programmed with various parameters. */ struct t4_sched_params { int8_t subcmd; /* sub-command */ int8_t type; /* packet or flow */ union { struct { /* sub-command SCHED_CLASS_CONFIG */ int8_t minmax; /* minmax enable */ } config; struct t4_sched_class_params params; uint8_t reserved[6 + 8 * 8]; } u; }; enum { SCHED_CLASS_SUBCMD_CONFIG, /* config sub-command */ SCHED_CLASS_SUBCMD_PARAMS, /* params sub-command */ }; enum { SCHED_CLASS_TYPE_PACKET, }; enum { SCHED_CLASS_LEVEL_CL_RL, /* class rate limiter */ SCHED_CLASS_LEVEL_CL_WRR, /* class weighted round robin */ SCHED_CLASS_LEVEL_CH_RL, /* channel rate limiter */ }; enum { SCHED_CLASS_MODE_CLASS, /* per-class scheduling */ SCHED_CLASS_MODE_FLOW, /* per-flow scheduling */ }; enum { SCHED_CLASS_RATEUNIT_BITS, /* bit rate scheduling */ SCHED_CLASS_RATEUNIT_PKTS, /* packet rate scheduling */ }; enum { SCHED_CLASS_RATEMODE_REL, /* percent of port bandwidth */ SCHED_CLASS_RATEMODE_ABS, /* Kb/s */ }; /* * Support for "sched_queue" command to allow one or more NIC TX Queues to be * bound to a TX Scheduling Class. */ struct t4_sched_queue { uint8_t port; int8_t queue; /* queue index; -1 => all queues */ int8_t cl; /* class index; -1 => unbind */ }; #define T4_SGE_CONTEXT_SIZE 24 enum { SGE_CONTEXT_EGRESS, SGE_CONTEXT_INGRESS, SGE_CONTEXT_FLM, SGE_CONTEXT_CNM }; struct t4_sge_context { uint32_t mem_id; uint32_t cid; uint32_t data[T4_SGE_CONTEXT_SIZE / 4]; }; struct t4_mem_range { uint32_t addr; uint32_t len; uint32_t *data; }; #define T4_TRACE_LEN 112 struct t4_trace_params { uint32_t data[T4_TRACE_LEN / 4]; uint32_t mask[T4_TRACE_LEN / 4]; uint16_t snap_len; uint16_t min_len; uint8_t skip_ofst; uint8_t skip_len; uint8_t invert; uint8_t port; }; struct t4_tracer { uint8_t idx; uint8_t enabled; uint8_t valid; struct t4_trace_params tp; }; +struct t4_cudbg_dump { + uint8_t wr_flash; + uint8_t bitmap[16]; + uint32_t len; + uint8_t *data; +}; + #define CHELSIO_T4_GETREG _IOWR('f', T4_GETREG, struct t4_reg) #define CHELSIO_T4_SETREG _IOW('f', T4_SETREG, struct t4_reg) #define CHELSIO_T4_REGDUMP _IOWR('f', T4_REGDUMP, struct t4_regdump) #define CHELSIO_T4_GET_FILTER_MODE _IOWR('f', T4_GET_FILTER_MODE, uint32_t) #define CHELSIO_T4_SET_FILTER_MODE _IOW('f', T4_SET_FILTER_MODE, uint32_t) #define CHELSIO_T4_GET_FILTER _IOWR('f', T4_GET_FILTER, struct t4_filter) #define CHELSIO_T4_SET_FILTER _IOW('f', T4_SET_FILTER, struct t4_filter) #define CHELSIO_T4_DEL_FILTER _IOW('f', T4_DEL_FILTER, struct t4_filter) #define CHELSIO_T4_GET_SGE_CONTEXT _IOWR('f', T4_GET_SGE_CONTEXT, \ struct t4_sge_context) #define CHELSIO_T4_LOAD_FW _IOW('f', T4_LOAD_FW, struct t4_data) #define CHELSIO_T4_GET_MEM _IOW('f', T4_GET_MEM, struct t4_mem_range) #define CHELSIO_T4_GET_I2C _IOWR('f', T4_GET_I2C, struct t4_i2c_data) #define CHELSIO_T4_CLEAR_STATS _IOW('f', T4_CLEAR_STATS, uint32_t) #define CHELSIO_T4_SCHED_CLASS _IOW('f', T4_SET_SCHED_CLASS, \ struct t4_sched_params) #define CHELSIO_T4_SCHED_QUEUE _IOW('f', T4_SET_SCHED_QUEUE, \ struct t4_sched_queue) #define CHELSIO_T4_GET_TRACER _IOWR('f', T4_GET_TRACER, struct t4_tracer) #define CHELSIO_T4_SET_TRACER _IOW('f', T4_SET_TRACER, struct t4_tracer) #define CHELSIO_T4_LOAD_CFG _IOW('f', T4_LOAD_CFG, struct t4_data) #define CHELSIO_T4_LOAD_BOOT _IOW('f', T4_LOAD_BOOT, struct t4_bootrom) #define CHELSIO_T4_LOAD_BOOTCFG _IOW('f', T4_LOAD_BOOTCFG, struct t4_data) +#define CHELSIO_T4_CUDBG_DUMP _IOWR('f', T4_CUDBG_DUMP, struct t4_cudbg_dump) #endif Index: projects/make-check-sandbox/sys/dev/cxgbe/t4_main.c =================================================================== --- projects/make-check-sandbox/sys/dev/cxgbe/t4_main.c (revision 322021) +++ projects/make-check-sandbox/sys/dev/cxgbe/t4_main.c (revision 322022) @@ -1,10078 +1,10126 @@ /*- * Copyright (c) 2011 Chelsio Communications, Inc. * All rights reserved. * Written by: Navdeep Parhar * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include "opt_ddb.h" #include "opt_inet.h" #include "opt_inet6.h" #include "opt_rss.h" #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef RSS #include #endif #if defined(__i386__) || defined(__amd64__) #include #include #endif #ifdef DDB #include #include #endif #include "common/common.h" #include "common/t4_msg.h" #include "common/t4_regs.h" #include "common/t4_regs_values.h" +#include "cudbg/cudbg.h" #include "t4_ioctl.h" #include "t4_l2t.h" #include "t4_mp_ring.h" #include "t4_if.h" /* T4 bus driver interface */ static int t4_probe(device_t); static int t4_attach(device_t); static int t4_detach(device_t); static int t4_ready(device_t); static int t4_read_port_device(device_t, int, device_t *); static device_method_t t4_methods[] = { DEVMETHOD(device_probe, t4_probe), DEVMETHOD(device_attach, t4_attach), DEVMETHOD(device_detach, t4_detach), DEVMETHOD(t4_is_main_ready, t4_ready), DEVMETHOD(t4_read_port_device, t4_read_port_device), DEVMETHOD_END }; static driver_t t4_driver = { "t4nex", t4_methods, sizeof(struct adapter) }; /* T4 port (cxgbe) interface */ static int cxgbe_probe(device_t); static int cxgbe_attach(device_t); static int cxgbe_detach(device_t); device_method_t cxgbe_methods[] = { DEVMETHOD(device_probe, cxgbe_probe), DEVMETHOD(device_attach, cxgbe_attach), DEVMETHOD(device_detach, cxgbe_detach), { 0, 0 } }; static driver_t cxgbe_driver = { "cxgbe", cxgbe_methods, sizeof(struct port_info) }; /* T4 VI (vcxgbe) interface */ static int vcxgbe_probe(device_t); static int vcxgbe_attach(device_t); static int vcxgbe_detach(device_t); static device_method_t vcxgbe_methods[] = { DEVMETHOD(device_probe, vcxgbe_probe), DEVMETHOD(device_attach, vcxgbe_attach), DEVMETHOD(device_detach, vcxgbe_detach), { 0, 0 } }; static driver_t vcxgbe_driver = { "vcxgbe", vcxgbe_methods, sizeof(struct vi_info) }; static d_ioctl_t t4_ioctl; static struct cdevsw t4_cdevsw = { .d_version = D_VERSION, .d_ioctl = t4_ioctl, .d_name = "t4nex", }; /* T5 bus driver interface */ static int t5_probe(device_t); static device_method_t t5_methods[] = { DEVMETHOD(device_probe, t5_probe), DEVMETHOD(device_attach, t4_attach), DEVMETHOD(device_detach, t4_detach), DEVMETHOD(t4_is_main_ready, t4_ready), DEVMETHOD(t4_read_port_device, t4_read_port_device), DEVMETHOD_END }; static driver_t t5_driver = { "t5nex", t5_methods, sizeof(struct adapter) }; /* T5 port (cxl) interface */ static driver_t cxl_driver = { "cxl", cxgbe_methods, sizeof(struct port_info) }; /* T5 VI (vcxl) interface */ static driver_t vcxl_driver = { "vcxl", vcxgbe_methods, sizeof(struct vi_info) }; /* T6 bus driver interface */ static int t6_probe(device_t); static device_method_t t6_methods[] = { DEVMETHOD(device_probe, t6_probe), DEVMETHOD(device_attach, t4_attach), DEVMETHOD(device_detach, t4_detach), DEVMETHOD(t4_is_main_ready, t4_ready), DEVMETHOD(t4_read_port_device, t4_read_port_device), DEVMETHOD_END }; static driver_t t6_driver = { "t6nex", t6_methods, sizeof(struct adapter) }; /* T6 port (cc) interface */ static driver_t cc_driver = { "cc", cxgbe_methods, sizeof(struct port_info) }; /* T6 VI (vcc) interface */ static driver_t vcc_driver = { "vcc", vcxgbe_methods, sizeof(struct vi_info) }; /* ifnet + media interface */ static void cxgbe_init(void *); static int cxgbe_ioctl(struct ifnet *, unsigned long, caddr_t); static int cxgbe_transmit(struct ifnet *, struct mbuf *); static void cxgbe_qflush(struct ifnet *); static int cxgbe_media_change(struct ifnet *); static void cxgbe_media_status(struct ifnet *, struct ifmediareq *); MALLOC_DEFINE(M_CXGBE, "cxgbe", "Chelsio T4/T5 Ethernet driver and services"); /* * Correct lock order when you need to acquire multiple locks is t4_list_lock, * then ADAPTER_LOCK, then t4_uld_list_lock. */ static struct sx t4_list_lock; SLIST_HEAD(, adapter) t4_list; #ifdef TCP_OFFLOAD static struct sx t4_uld_list_lock; SLIST_HEAD(, uld_info) t4_uld_list; #endif /* * Tunables. See tweak_tunables() too. * * Each tunable is set to a default value here if it's known at compile-time. * Otherwise it is set to -n as an indication to tweak_tunables() that it should * provide a reasonable default (upto n) when the driver is loaded. * * Tunables applicable to both T4 and T5 are under hw.cxgbe. Those specific to * T5 are under hw.cxl. */ /* * Number of queues for tx and rx, 10G and 1G, NIC and offload. */ #define NTXQ_10G 16 int t4_ntxq10g = -NTXQ_10G; TUNABLE_INT("hw.cxgbe.ntxq10g", &t4_ntxq10g); #define NRXQ_10G 8 int t4_nrxq10g = -NRXQ_10G; TUNABLE_INT("hw.cxgbe.nrxq10g", &t4_nrxq10g); #define NTXQ_1G 4 int t4_ntxq1g = -NTXQ_1G; TUNABLE_INT("hw.cxgbe.ntxq1g", &t4_ntxq1g); #define NRXQ_1G 2 int t4_nrxq1g = -NRXQ_1G; TUNABLE_INT("hw.cxgbe.nrxq1g", &t4_nrxq1g); #define NTXQ_VI 1 static int t4_ntxq_vi = -NTXQ_VI; TUNABLE_INT("hw.cxgbe.ntxq_vi", &t4_ntxq_vi); #define NRXQ_VI 1 static int t4_nrxq_vi = -NRXQ_VI; TUNABLE_INT("hw.cxgbe.nrxq_vi", &t4_nrxq_vi); static int t4_rsrv_noflowq = 0; TUNABLE_INT("hw.cxgbe.rsrv_noflowq", &t4_rsrv_noflowq); #ifdef TCP_OFFLOAD #define NOFLDTXQ_10G 8 static int t4_nofldtxq10g = -NOFLDTXQ_10G; TUNABLE_INT("hw.cxgbe.nofldtxq10g", &t4_nofldtxq10g); #define NOFLDRXQ_10G 2 static int t4_nofldrxq10g = -NOFLDRXQ_10G; TUNABLE_INT("hw.cxgbe.nofldrxq10g", &t4_nofldrxq10g); #define NOFLDTXQ_1G 2 static int t4_nofldtxq1g = -NOFLDTXQ_1G; TUNABLE_INT("hw.cxgbe.nofldtxq1g", &t4_nofldtxq1g); #define NOFLDRXQ_1G 1 static int t4_nofldrxq1g = -NOFLDRXQ_1G; TUNABLE_INT("hw.cxgbe.nofldrxq1g", &t4_nofldrxq1g); #define NOFLDTXQ_VI 1 static int t4_nofldtxq_vi = -NOFLDTXQ_VI; TUNABLE_INT("hw.cxgbe.nofldtxq_vi", &t4_nofldtxq_vi); #define NOFLDRXQ_VI 1 static int t4_nofldrxq_vi = -NOFLDRXQ_VI; TUNABLE_INT("hw.cxgbe.nofldrxq_vi", &t4_nofldrxq_vi); #endif #ifdef DEV_NETMAP #define NNMTXQ_VI 2 static int t4_nnmtxq_vi = -NNMTXQ_VI; TUNABLE_INT("hw.cxgbe.nnmtxq_vi", &t4_nnmtxq_vi); #define NNMRXQ_VI 2 static int t4_nnmrxq_vi = -NNMRXQ_VI; TUNABLE_INT("hw.cxgbe.nnmrxq_vi", &t4_nnmrxq_vi); #endif /* * Holdoff parameters for 10G and 1G ports. */ #define TMR_IDX_10G 1 int t4_tmr_idx_10g = TMR_IDX_10G; TUNABLE_INT("hw.cxgbe.holdoff_timer_idx_10G", &t4_tmr_idx_10g); #define PKTC_IDX_10G (-1) int t4_pktc_idx_10g = PKTC_IDX_10G; TUNABLE_INT("hw.cxgbe.holdoff_pktc_idx_10G", &t4_pktc_idx_10g); #define TMR_IDX_1G 1 int t4_tmr_idx_1g = TMR_IDX_1G; TUNABLE_INT("hw.cxgbe.holdoff_timer_idx_1G", &t4_tmr_idx_1g); #define PKTC_IDX_1G (-1) int t4_pktc_idx_1g = PKTC_IDX_1G; TUNABLE_INT("hw.cxgbe.holdoff_pktc_idx_1G", &t4_pktc_idx_1g); /* * Size (# of entries) of each tx and rx queue. */ unsigned int t4_qsize_txq = TX_EQ_QSIZE; TUNABLE_INT("hw.cxgbe.qsize_txq", &t4_qsize_txq); unsigned int t4_qsize_rxq = RX_IQ_QSIZE; TUNABLE_INT("hw.cxgbe.qsize_rxq", &t4_qsize_rxq); /* * Interrupt types allowed (bits 0, 1, 2 = INTx, MSI, MSI-X respectively). */ int t4_intr_types = INTR_MSIX | INTR_MSI | INTR_INTX; TUNABLE_INT("hw.cxgbe.interrupt_types", &t4_intr_types); /* * Configuration file. */ #define DEFAULT_CF "default" #define FLASH_CF "flash" #define UWIRE_CF "uwire" #define FPGA_CF "fpga" static char t4_cfg_file[32] = DEFAULT_CF; TUNABLE_STR("hw.cxgbe.config_file", t4_cfg_file, sizeof(t4_cfg_file)); /* * PAUSE settings (bit 0, 1 = rx_pause, tx_pause respectively). * rx_pause = 1 to heed incoming PAUSE frames, 0 to ignore them. * tx_pause = 1 to emit PAUSE frames when the rx FIFO reaches its high water * mark or when signalled to do so, 0 to never emit PAUSE. */ static int t4_pause_settings = PAUSE_TX | PAUSE_RX; TUNABLE_INT("hw.cxgbe.pause_settings", &t4_pause_settings); /* * Forward Error Correction settings (bit 0, 1, 2 = FEC_RS, FEC_BASER_RS, * FEC_RESERVED respectively). * -1 to run with the firmware default. * 0 to disable FEC. */ static int t4_fec = -1; TUNABLE_INT("hw.cxgbe.fec", &t4_fec); /* * Link autonegotiation. * -1 to run with the firmware default. * 0 to disable. * 1 to enable. */ static int t4_autoneg = -1; TUNABLE_INT("hw.cxgbe.autoneg", &t4_autoneg); /* * Firmware auto-install by driver during attach (0, 1, 2 = prohibited, allowed, * encouraged respectively). */ static unsigned int t4_fw_install = 1; TUNABLE_INT("hw.cxgbe.fw_install", &t4_fw_install); /* * ASIC features that will be used. Disable the ones you don't want so that the * chip resources aren't wasted on features that will not be used. */ static int t4_nbmcaps_allowed = 0; TUNABLE_INT("hw.cxgbe.nbmcaps_allowed", &t4_nbmcaps_allowed); static int t4_linkcaps_allowed = 0; /* No DCBX, PPP, etc. by default */ TUNABLE_INT("hw.cxgbe.linkcaps_allowed", &t4_linkcaps_allowed); static int t4_switchcaps_allowed = FW_CAPS_CONFIG_SWITCH_INGRESS | FW_CAPS_CONFIG_SWITCH_EGRESS; TUNABLE_INT("hw.cxgbe.switchcaps_allowed", &t4_switchcaps_allowed); static int t4_niccaps_allowed = FW_CAPS_CONFIG_NIC; TUNABLE_INT("hw.cxgbe.niccaps_allowed", &t4_niccaps_allowed); static int t4_toecaps_allowed = -1; TUNABLE_INT("hw.cxgbe.toecaps_allowed", &t4_toecaps_allowed); static int t4_rdmacaps_allowed = -1; TUNABLE_INT("hw.cxgbe.rdmacaps_allowed", &t4_rdmacaps_allowed); static int t4_cryptocaps_allowed = 0; TUNABLE_INT("hw.cxgbe.cryptocaps_allowed", &t4_cryptocaps_allowed); static int t4_iscsicaps_allowed = -1; TUNABLE_INT("hw.cxgbe.iscsicaps_allowed", &t4_iscsicaps_allowed); static int t4_fcoecaps_allowed = 0; TUNABLE_INT("hw.cxgbe.fcoecaps_allowed", &t4_fcoecaps_allowed); static int t5_write_combine = 0; TUNABLE_INT("hw.cxl.write_combine", &t5_write_combine); static int t4_num_vis = 1; TUNABLE_INT("hw.cxgbe.num_vis", &t4_num_vis); /* Functions used by extra VIs to obtain unique MAC addresses for each VI. */ static int vi_mac_funcs[] = { FW_VI_FUNC_OFLD, FW_VI_FUNC_IWARP, FW_VI_FUNC_OPENISCSI, FW_VI_FUNC_OPENFCOE, FW_VI_FUNC_FOISCSI, FW_VI_FUNC_FOFCOE, }; struct intrs_and_queues { uint16_t intr_type; /* INTx, MSI, or MSI-X */ uint16_t nirq; /* Total # of vectors */ uint16_t intr_flags_10g;/* Interrupt flags for each 10G port */ uint16_t intr_flags_1g; /* Interrupt flags for each 1G port */ uint16_t ntxq10g; /* # of NIC txq's for each 10G port */ uint16_t nrxq10g; /* # of NIC rxq's for each 10G port */ uint16_t ntxq1g; /* # of NIC txq's for each 1G port */ uint16_t nrxq1g; /* # of NIC rxq's for each 1G port */ uint16_t rsrv_noflowq; /* Flag whether to reserve queue 0 */ uint16_t nofldtxq10g; /* # of TOE txq's for each 10G port */ uint16_t nofldrxq10g; /* # of TOE rxq's for each 10G port */ uint16_t nofldtxq1g; /* # of TOE txq's for each 1G port */ uint16_t nofldrxq1g; /* # of TOE rxq's for each 1G port */ /* The vcxgbe/vcxl interfaces use these and not the ones above. */ uint16_t ntxq_vi; /* # of NIC txq's */ uint16_t nrxq_vi; /* # of NIC rxq's */ uint16_t nofldtxq_vi; /* # of TOE txq's */ uint16_t nofldrxq_vi; /* # of TOE rxq's */ uint16_t nnmtxq_vi; /* # of netmap txq's */ uint16_t nnmrxq_vi; /* # of netmap rxq's */ }; struct filter_entry { uint32_t valid:1; /* filter allocated and valid */ uint32_t locked:1; /* filter is administratively locked */ uint32_t pending:1; /* filter action is pending firmware reply */ uint32_t smtidx:8; /* Source MAC Table index for smac */ struct l2t_entry *l2t; /* Layer Two Table entry for dmac */ struct t4_filter_specification fs; }; static void setup_memwin(struct adapter *); static void position_memwin(struct adapter *, int, uint32_t); static int rw_via_memwin(struct adapter *, int, uint32_t, uint32_t *, int, int); static inline int read_via_memwin(struct adapter *, int, uint32_t, uint32_t *, int); static inline int write_via_memwin(struct adapter *, int, uint32_t, const uint32_t *, int); static int validate_mem_range(struct adapter *, uint32_t, int); static int fwmtype_to_hwmtype(int); static int validate_mt_off_len(struct adapter *, int, uint32_t, int, uint32_t *); static int fixup_devlog_params(struct adapter *); static int cfg_itype_and_nqueues(struct adapter *, int, int, int, struct intrs_and_queues *); static int prep_firmware(struct adapter *); static int partition_resources(struct adapter *, const struct firmware *, const char *); static int get_params__pre_init(struct adapter *); static int get_params__post_init(struct adapter *); static int set_params__post_init(struct adapter *); static void t4_set_desc(struct adapter *); static void build_medialist(struct port_info *, struct ifmedia *); static void init_l1cfg(struct port_info *); static int cxgbe_init_synchronized(struct vi_info *); static int cxgbe_uninit_synchronized(struct vi_info *); static void quiesce_txq(struct adapter *, struct sge_txq *); static void quiesce_wrq(struct adapter *, struct sge_wrq *); static void quiesce_iq(struct adapter *, struct sge_iq *); static void quiesce_fl(struct adapter *, struct sge_fl *); static int t4_alloc_irq(struct adapter *, struct irq *, int rid, driver_intr_t *, void *, char *); static int t4_free_irq(struct adapter *, struct irq *); static void get_regs(struct adapter *, struct t4_regdump *, uint8_t *); static void vi_refresh_stats(struct adapter *, struct vi_info *); static void cxgbe_refresh_stats(struct adapter *, struct port_info *); static void cxgbe_tick(void *); static void cxgbe_vlan_config(void *, struct ifnet *, uint16_t); static void cxgbe_sysctls(struct port_info *); static int sysctl_int_array(SYSCTL_HANDLER_ARGS); static int sysctl_bitfield(SYSCTL_HANDLER_ARGS); static int sysctl_btphy(SYSCTL_HANDLER_ARGS); static int sysctl_noflowq(SYSCTL_HANDLER_ARGS); static int sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS); static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS); static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS); static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS); static int sysctl_pause_settings(SYSCTL_HANDLER_ARGS); static int sysctl_fec(SYSCTL_HANDLER_ARGS); static int sysctl_autoneg(SYSCTL_HANDLER_ARGS); static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS); static int sysctl_temperature(SYSCTL_HANDLER_ARGS); #ifdef SBUF_DRAIN static int sysctl_cctrl(SYSCTL_HANDLER_ARGS); static int sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS); static int sysctl_cim_la(SYSCTL_HANDLER_ARGS); static int sysctl_cim_la_t6(SYSCTL_HANDLER_ARGS); static int sysctl_cim_ma_la(SYSCTL_HANDLER_ARGS); static int sysctl_cim_pif_la(SYSCTL_HANDLER_ARGS); static int sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS); static int sysctl_cpl_stats(SYSCTL_HANDLER_ARGS); static int sysctl_ddp_stats(SYSCTL_HANDLER_ARGS); static int sysctl_devlog(SYSCTL_HANDLER_ARGS); static int sysctl_fcoe_stats(SYSCTL_HANDLER_ARGS); static int sysctl_hw_sched(SYSCTL_HANDLER_ARGS); static int sysctl_lb_stats(SYSCTL_HANDLER_ARGS); static int sysctl_linkdnrc(SYSCTL_HANDLER_ARGS); static int sysctl_meminfo(SYSCTL_HANDLER_ARGS); static int sysctl_mps_tcam(SYSCTL_HANDLER_ARGS); static int sysctl_mps_tcam_t6(SYSCTL_HANDLER_ARGS); static int sysctl_path_mtus(SYSCTL_HANDLER_ARGS); static int sysctl_pm_stats(SYSCTL_HANDLER_ARGS); static int sysctl_rdma_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tcp_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tids(SYSCTL_HANDLER_ARGS); static int sysctl_tp_err_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tp_la_mask(SYSCTL_HANDLER_ARGS); static int sysctl_tp_la(SYSCTL_HANDLER_ARGS); static int sysctl_tx_rate(SYSCTL_HANDLER_ARGS); static int sysctl_ulprx_la(SYSCTL_HANDLER_ARGS); static int sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS); static int sysctl_tc_params(SYSCTL_HANDLER_ARGS); #endif #ifdef TCP_OFFLOAD static int sysctl_tp_tick(SYSCTL_HANDLER_ARGS); static int sysctl_tp_dack_timer(SYSCTL_HANDLER_ARGS); static int sysctl_tp_timer(SYSCTL_HANDLER_ARGS); static int sysctl_tp_shift_cnt(SYSCTL_HANDLER_ARGS); static int sysctl_tp_backoff(SYSCTL_HANDLER_ARGS); #endif static uint32_t fconf_iconf_to_mode(uint32_t, uint32_t); static uint32_t mode_to_fconf(uint32_t); static uint32_t mode_to_iconf(uint32_t); static int check_fspec_against_fconf_iconf(struct adapter *, struct t4_filter_specification *); static int get_filter_mode(struct adapter *, uint32_t *); static int set_filter_mode(struct adapter *, uint32_t); static inline uint64_t get_filter_hits(struct adapter *, uint32_t); static int get_filter(struct adapter *, struct t4_filter *); static int set_filter(struct adapter *, struct t4_filter *); static int del_filter(struct adapter *, struct t4_filter *); static void clear_filter(struct filter_entry *); static int set_filter_wr(struct adapter *, int); static int del_filter_wr(struct adapter *, int); static int set_tcb_rpl(struct sge_iq *, const struct rss_header *, struct mbuf *); static int get_sge_context(struct adapter *, struct t4_sge_context *); static int load_fw(struct adapter *, struct t4_data *); static int load_cfg(struct adapter *, struct t4_data *); static int load_boot(struct adapter *, struct t4_bootrom *); static int load_bootcfg(struct adapter *, struct t4_data *); +static int cudbg_dump(struct adapter *, struct t4_cudbg_dump *); static int read_card_mem(struct adapter *, int, struct t4_mem_range *); static int read_i2c(struct adapter *, struct t4_i2c_data *); #ifdef TCP_OFFLOAD static int toe_capability(struct vi_info *, int); #endif static int mod_event(module_t, int, void *); static int notify_siblings(device_t, int); struct { uint16_t device; char *desc; } t4_pciids[] = { {0xa000, "Chelsio Terminator 4 FPGA"}, {0x4400, "Chelsio T440-dbg"}, {0x4401, "Chelsio T420-CR"}, {0x4402, "Chelsio T422-CR"}, {0x4403, "Chelsio T440-CR"}, {0x4404, "Chelsio T420-BCH"}, {0x4405, "Chelsio T440-BCH"}, {0x4406, "Chelsio T440-CH"}, {0x4407, "Chelsio T420-SO"}, {0x4408, "Chelsio T420-CX"}, {0x4409, "Chelsio T420-BT"}, {0x440a, "Chelsio T404-BT"}, {0x440e, "Chelsio T440-LP-CR"}, }, t5_pciids[] = { {0xb000, "Chelsio Terminator 5 FPGA"}, {0x5400, "Chelsio T580-dbg"}, {0x5401, "Chelsio T520-CR"}, /* 2 x 10G */ {0x5402, "Chelsio T522-CR"}, /* 2 x 10G, 2 X 1G */ {0x5403, "Chelsio T540-CR"}, /* 4 x 10G */ {0x5407, "Chelsio T520-SO"}, /* 2 x 10G, nomem */ {0x5409, "Chelsio T520-BT"}, /* 2 x 10GBaseT */ {0x540a, "Chelsio T504-BT"}, /* 4 x 1G */ {0x540d, "Chelsio T580-CR"}, /* 2 x 40G */ {0x540e, "Chelsio T540-LP-CR"}, /* 4 x 10G */ {0x5410, "Chelsio T580-LP-CR"}, /* 2 x 40G */ {0x5411, "Chelsio T520-LL-CR"}, /* 2 x 10G */ {0x5412, "Chelsio T560-CR"}, /* 1 x 40G, 2 x 10G */ {0x5414, "Chelsio T580-LP-SO-CR"}, /* 2 x 40G, nomem */ {0x5415, "Chelsio T502-BT"}, /* 2 x 1G */ #ifdef notyet {0x5404, "Chelsio T520-BCH"}, {0x5405, "Chelsio T540-BCH"}, {0x5406, "Chelsio T540-CH"}, {0x5408, "Chelsio T520-CX"}, {0x540b, "Chelsio B520-SR"}, {0x540c, "Chelsio B504-BT"}, {0x540f, "Chelsio Amsterdam"}, {0x5413, "Chelsio T580-CHR"}, #endif }, t6_pciids[] = { {0xc006, "Chelsio Terminator 6 FPGA"}, /* T6 PE10K6 FPGA (PF0) */ {0x6400, "Chelsio T6-DBG-25"}, /* 2 x 10/25G, debug */ {0x6401, "Chelsio T6225-CR"}, /* 2 x 10/25G */ {0x6402, "Chelsio T6225-SO-CR"}, /* 2 x 10/25G, nomem */ {0x6403, "Chelsio T6425-CR"}, /* 4 x 10/25G */ {0x6404, "Chelsio T6425-SO-CR"}, /* 4 x 10/25G, nomem */ {0x6405, "Chelsio T6225-OCP-SO"}, /* 2 x 10/25G, nomem */ {0x6406, "Chelsio T62100-OCP-SO"}, /* 2 x 40/50/100G, nomem */ {0x6407, "Chelsio T62100-LP-CR"}, /* 2 x 40/50/100G */ {0x6408, "Chelsio T62100-SO-CR"}, /* 2 x 40/50/100G, nomem */ {0x6409, "Chelsio T6210-BT"}, /* 2 x 10GBASE-T */ {0x640d, "Chelsio T62100-CR"}, /* 2 x 40/50/100G */ {0x6410, "Chelsio T6-DBG-100"}, /* 2 x 40/50/100G, debug */ {0x6411, "Chelsio T6225-LL-CR"}, /* 2 x 10/25G */ {0x6414, "Chelsio T61100-OCP-SO"}, /* 1 x 40/50/100G, nomem */ {0x6415, "Chelsio T6201-BT"}, /* 2 x 1000BASE-T */ /* Custom */ {0x6480, "Chelsio T6225 80"}, {0x6481, "Chelsio T62100 81"}, }; #ifdef TCP_OFFLOAD /* * service_iq() has an iq and needs the fl. Offset of fl from the iq should be * exactly the same for both rxq and ofld_rxq. */ CTASSERT(offsetof(struct sge_ofld_rxq, iq) == offsetof(struct sge_rxq, iq)); CTASSERT(offsetof(struct sge_ofld_rxq, fl) == offsetof(struct sge_rxq, fl)); #endif CTASSERT(sizeof(struct cluster_metadata) <= CL_METADATA_SIZE); static int t4_probe(device_t dev) { int i; uint16_t v = pci_get_vendor(dev); uint16_t d = pci_get_device(dev); uint8_t f = pci_get_function(dev); if (v != PCI_VENDOR_ID_CHELSIO) return (ENXIO); /* Attach only to PF0 of the FPGA */ if (d == 0xa000 && f != 0) return (ENXIO); for (i = 0; i < nitems(t4_pciids); i++) { if (d == t4_pciids[i].device) { device_set_desc(dev, t4_pciids[i].desc); return (BUS_PROBE_DEFAULT); } } return (ENXIO); } static int t5_probe(device_t dev) { int i; uint16_t v = pci_get_vendor(dev); uint16_t d = pci_get_device(dev); uint8_t f = pci_get_function(dev); if (v != PCI_VENDOR_ID_CHELSIO) return (ENXIO); /* Attach only to PF0 of the FPGA */ if (d == 0xb000 && f != 0) return (ENXIO); for (i = 0; i < nitems(t5_pciids); i++) { if (d == t5_pciids[i].device) { device_set_desc(dev, t5_pciids[i].desc); return (BUS_PROBE_DEFAULT); } } return (ENXIO); } static int t6_probe(device_t dev) { int i; uint16_t v = pci_get_vendor(dev); uint16_t d = pci_get_device(dev); if (v != PCI_VENDOR_ID_CHELSIO) return (ENXIO); for (i = 0; i < nitems(t6_pciids); i++) { if (d == t6_pciids[i].device) { device_set_desc(dev, t6_pciids[i].desc); return (BUS_PROBE_DEFAULT); } } return (ENXIO); } static void t5_attribute_workaround(device_t dev) { device_t root_port; uint32_t v; /* * The T5 chips do not properly echo the No Snoop and Relaxed * Ordering attributes when replying to a TLP from a Root * Port. As a workaround, find the parent Root Port and * disable No Snoop and Relaxed Ordering. Note that this * affects all devices under this root port. */ root_port = pci_find_pcie_root_port(dev); if (root_port == NULL) { device_printf(dev, "Unable to find parent root port\n"); return; } v = pcie_adjust_config(root_port, PCIER_DEVICE_CTL, PCIEM_CTL_RELAXED_ORD_ENABLE | PCIEM_CTL_NOSNOOP_ENABLE, 0, 2); if ((v & (PCIEM_CTL_RELAXED_ORD_ENABLE | PCIEM_CTL_NOSNOOP_ENABLE)) != 0) device_printf(dev, "Disabled No Snoop/Relaxed Ordering on %s\n", device_get_nameunit(root_port)); } static const struct devnames devnames[] = { { .nexus_name = "t4nex", .ifnet_name = "cxgbe", .vi_ifnet_name = "vcxgbe", .pf03_drv_name = "t4iov", .vf_nexus_name = "t4vf", .vf_ifnet_name = "cxgbev" }, { .nexus_name = "t5nex", .ifnet_name = "cxl", .vi_ifnet_name = "vcxl", .pf03_drv_name = "t5iov", .vf_nexus_name = "t5vf", .vf_ifnet_name = "cxlv" }, { .nexus_name = "t6nex", .ifnet_name = "cc", .vi_ifnet_name = "vcc", .pf03_drv_name = "t6iov", .vf_nexus_name = "t6vf", .vf_ifnet_name = "ccv" } }; void t4_init_devnames(struct adapter *sc) { int id; id = chip_id(sc); if (id >= CHELSIO_T4 && id - CHELSIO_T4 < nitems(devnames)) sc->names = &devnames[id - CHELSIO_T4]; else { device_printf(sc->dev, "chip id %d is not supported.\n", id); sc->names = NULL; } } static int t4_attach(device_t dev) { struct adapter *sc; int rc = 0, i, j, n10g, n1g, rqidx, tqidx; struct make_dev_args mda; struct intrs_and_queues iaq; struct sge *s; uint8_t *buf; #ifdef TCP_OFFLOAD int ofld_rqidx, ofld_tqidx; #endif #ifdef DEV_NETMAP int nm_rqidx, nm_tqidx; #endif int num_vis; sc = device_get_softc(dev); sc->dev = dev; TUNABLE_INT_FETCH("hw.cxgbe.dflags", &sc->debug_flags); if ((pci_get_device(dev) & 0xff00) == 0x5400) t5_attribute_workaround(dev); pci_enable_busmaster(dev); if (pci_find_cap(dev, PCIY_EXPRESS, &i) == 0) { uint32_t v; pci_set_max_read_req(dev, 4096); v = pci_read_config(dev, i + PCIER_DEVICE_CTL, 2); v |= PCIEM_CTL_RELAXED_ORD_ENABLE; pci_write_config(dev, i + PCIER_DEVICE_CTL, v, 2); sc->params.pci.mps = 128 << ((v & PCIEM_CTL_MAX_PAYLOAD) >> 5); } sc->sge_gts_reg = MYPF_REG(A_SGE_PF_GTS); sc->sge_kdoorbell_reg = MYPF_REG(A_SGE_PF_KDOORBELL); sc->traceq = -1; mtx_init(&sc->ifp_lock, sc->ifp_lockname, 0, MTX_DEF); snprintf(sc->ifp_lockname, sizeof(sc->ifp_lockname), "%s tracer", device_get_nameunit(dev)); snprintf(sc->lockname, sizeof(sc->lockname), "%s", device_get_nameunit(dev)); mtx_init(&sc->sc_lock, sc->lockname, 0, MTX_DEF); t4_add_adapter(sc); mtx_init(&sc->sfl_lock, "starving freelists", 0, MTX_DEF); TAILQ_INIT(&sc->sfl); callout_init_mtx(&sc->sfl_callout, &sc->sfl_lock, 0); mtx_init(&sc->reg_lock, "indirect register access", 0, MTX_DEF); rc = t4_map_bars_0_and_4(sc); if (rc != 0) goto done; /* error message displayed already */ memset(sc->chan_map, 0xff, sizeof(sc->chan_map)); /* Prepare the adapter for operation. */ buf = malloc(PAGE_SIZE, M_CXGBE, M_ZERO | M_WAITOK); rc = -t4_prep_adapter(sc, buf); free(buf, M_CXGBE); if (rc != 0) { device_printf(dev, "failed to prepare adapter: %d.\n", rc); goto done; } /* * This is the real PF# to which we're attaching. Works from within PCI * passthrough environments too, where pci_get_function() could return a * different PF# depending on the passthrough configuration. We need to * use the real PF# in all our communication with the firmware. */ j = t4_read_reg(sc, A_PL_WHOAMI); sc->pf = chip_id(sc) <= CHELSIO_T5 ? G_SOURCEPF(j) : G_T6_SOURCEPF(j); sc->mbox = sc->pf; t4_init_devnames(sc); if (sc->names == NULL) { rc = ENOTSUP; goto done; /* error message displayed already */ } /* * Do this really early, with the memory windows set up even before the * character device. The userland tool's register i/o and mem read * will work even in "recovery mode". */ setup_memwin(sc); if (t4_init_devlog_params(sc, 0) == 0) fixup_devlog_params(sc); make_dev_args_init(&mda); mda.mda_devsw = &t4_cdevsw; mda.mda_uid = UID_ROOT; mda.mda_gid = GID_WHEEL; mda.mda_mode = 0600; mda.mda_si_drv1 = sc; rc = make_dev_s(&mda, &sc->cdev, "%s", device_get_nameunit(dev)); if (rc != 0) device_printf(dev, "failed to create nexus char device: %d.\n", rc); /* Go no further if recovery mode has been requested. */ if (TUNABLE_INT_FETCH("hw.cxgbe.sos", &i) && i != 0) { device_printf(dev, "recovery mode.\n"); goto done; } #if defined(__i386__) if ((cpu_feature & CPUID_CX8) == 0) { device_printf(dev, "64 bit atomics not available.\n"); rc = ENOTSUP; goto done; } #endif /* Prepare the firmware for operation */ rc = prep_firmware(sc); if (rc != 0) goto done; /* error message displayed already */ rc = get_params__post_init(sc); if (rc != 0) goto done; /* error message displayed already */ rc = set_params__post_init(sc); if (rc != 0) goto done; /* error message displayed already */ rc = t4_map_bar_2(sc); if (rc != 0) goto done; /* error message displayed already */ rc = t4_create_dma_tag(sc); if (rc != 0) goto done; /* error message displayed already */ /* * Number of VIs to create per-port. The first VI is the "main" regular * VI for the port. The rest are additional virtual interfaces on the * same physical port. Note that the main VI does not have native * netmap support but the extra VIs do. * * Limit the number of VIs per port to the number of available * MAC addresses per port. */ if (t4_num_vis >= 1) num_vis = t4_num_vis; else num_vis = 1; if (num_vis > nitems(vi_mac_funcs)) { num_vis = nitems(vi_mac_funcs); device_printf(dev, "Number of VIs limited to %d\n", num_vis); } /* * First pass over all the ports - allocate VIs and initialize some * basic parameters like mac address, port type, etc. We also figure * out whether a port is 10G or 1G and use that information when * calculating how many interrupts to attempt to allocate. */ n10g = n1g = 0; for_each_port(sc, i) { struct port_info *pi; pi = malloc(sizeof(*pi), M_CXGBE, M_ZERO | M_WAITOK); sc->port[i] = pi; /* These must be set before t4_port_init */ pi->adapter = sc; pi->port_id = i; /* * XXX: vi[0] is special so we can't delay this allocation until * pi->nvi's final value is known. */ pi->vi = malloc(sizeof(struct vi_info) * num_vis, M_CXGBE, M_ZERO | M_WAITOK); /* * Allocate the "main" VI and initialize parameters * like mac addr. */ rc = -t4_port_init(sc, sc->mbox, sc->pf, 0, i); if (rc != 0) { device_printf(dev, "unable to initialize port %d: %d\n", i, rc); free(pi->vi, M_CXGBE); free(pi, M_CXGBE); sc->port[i] = NULL; goto done; } snprintf(pi->lockname, sizeof(pi->lockname), "%sp%d", device_get_nameunit(dev), i); mtx_init(&pi->pi_lock, pi->lockname, 0, MTX_DEF); sc->chan_map[pi->tx_chan] = i; if (port_top_speed(pi) >= 10) { n10g++; } else { n1g++; } pi->dev = device_add_child(dev, sc->names->ifnet_name, -1); if (pi->dev == NULL) { device_printf(dev, "failed to add device for port %d.\n", i); rc = ENXIO; goto done; } pi->vi[0].dev = pi->dev; device_set_softc(pi->dev, pi); } /* * Interrupt type, # of interrupts, # of rx/tx queues, etc. */ rc = cfg_itype_and_nqueues(sc, n10g, n1g, num_vis, &iaq); if (rc != 0) goto done; /* error message displayed already */ if (iaq.nrxq_vi + iaq.nofldrxq_vi + iaq.nnmrxq_vi == 0) num_vis = 1; sc->intr_type = iaq.intr_type; sc->intr_count = iaq.nirq; s = &sc->sge; s->nrxq = n10g * iaq.nrxq10g + n1g * iaq.nrxq1g; s->ntxq = n10g * iaq.ntxq10g + n1g * iaq.ntxq1g; if (num_vis > 1) { s->nrxq += (n10g + n1g) * (num_vis - 1) * iaq.nrxq_vi; s->ntxq += (n10g + n1g) * (num_vis - 1) * iaq.ntxq_vi; } s->neq = s->ntxq + s->nrxq; /* the free list in an rxq is an eq */ s->neq += sc->params.nports + 1;/* ctrl queues: 1 per port + 1 mgmt */ s->niq = s->nrxq + 1; /* 1 extra for firmware event queue */ #ifdef TCP_OFFLOAD if (is_offload(sc)) { s->nofldrxq = n10g * iaq.nofldrxq10g + n1g * iaq.nofldrxq1g; s->nofldtxq = n10g * iaq.nofldtxq10g + n1g * iaq.nofldtxq1g; if (num_vis > 1) { s->nofldrxq += (n10g + n1g) * (num_vis - 1) * iaq.nofldrxq_vi; s->nofldtxq += (n10g + n1g) * (num_vis - 1) * iaq.nofldtxq_vi; } s->neq += s->nofldtxq + s->nofldrxq; s->niq += s->nofldrxq; s->ofld_rxq = malloc(s->nofldrxq * sizeof(struct sge_ofld_rxq), M_CXGBE, M_ZERO | M_WAITOK); s->ofld_txq = malloc(s->nofldtxq * sizeof(struct sge_wrq), M_CXGBE, M_ZERO | M_WAITOK); } #endif #ifdef DEV_NETMAP if (num_vis > 1) { s->nnmrxq = (n10g + n1g) * (num_vis - 1) * iaq.nnmrxq_vi; s->nnmtxq = (n10g + n1g) * (num_vis - 1) * iaq.nnmtxq_vi; } s->neq += s->nnmtxq + s->nnmrxq; s->niq += s->nnmrxq; s->nm_rxq = malloc(s->nnmrxq * sizeof(struct sge_nm_rxq), M_CXGBE, M_ZERO | M_WAITOK); s->nm_txq = malloc(s->nnmtxq * sizeof(struct sge_nm_txq), M_CXGBE, M_ZERO | M_WAITOK); #endif s->ctrlq = malloc(sc->params.nports * sizeof(struct sge_wrq), M_CXGBE, M_ZERO | M_WAITOK); s->rxq = malloc(s->nrxq * sizeof(struct sge_rxq), M_CXGBE, M_ZERO | M_WAITOK); s->txq = malloc(s->ntxq * sizeof(struct sge_txq), M_CXGBE, M_ZERO | M_WAITOK); s->iqmap = malloc(s->niq * sizeof(struct sge_iq *), M_CXGBE, M_ZERO | M_WAITOK); s->eqmap = malloc(s->neq * sizeof(struct sge_eq *), M_CXGBE, M_ZERO | M_WAITOK); sc->irq = malloc(sc->intr_count * sizeof(struct irq), M_CXGBE, M_ZERO | M_WAITOK); t4_init_l2t(sc, M_WAITOK); t4_init_tx_sched(sc); /* * Second pass over the ports. This time we know the number of rx and * tx queues that each port should get. */ rqidx = tqidx = 0; #ifdef TCP_OFFLOAD ofld_rqidx = ofld_tqidx = 0; #endif #ifdef DEV_NETMAP nm_rqidx = nm_tqidx = 0; #endif for_each_port(sc, i) { struct port_info *pi = sc->port[i]; struct vi_info *vi; if (pi == NULL) continue; pi->nvi = num_vis; for_each_vi(pi, j, vi) { vi->pi = pi; vi->qsize_rxq = t4_qsize_rxq; vi->qsize_txq = t4_qsize_txq; vi->first_rxq = rqidx; vi->first_txq = tqidx; if (port_top_speed(pi) >= 10) { vi->tmr_idx = t4_tmr_idx_10g; vi->pktc_idx = t4_pktc_idx_10g; vi->flags |= iaq.intr_flags_10g & INTR_RXQ; vi->nrxq = j == 0 ? iaq.nrxq10g : iaq.nrxq_vi; vi->ntxq = j == 0 ? iaq.ntxq10g : iaq.ntxq_vi; } else { vi->tmr_idx = t4_tmr_idx_1g; vi->pktc_idx = t4_pktc_idx_1g; vi->flags |= iaq.intr_flags_1g & INTR_RXQ; vi->nrxq = j == 0 ? iaq.nrxq1g : iaq.nrxq_vi; vi->ntxq = j == 0 ? iaq.ntxq1g : iaq.ntxq_vi; } rqidx += vi->nrxq; tqidx += vi->ntxq; if (j == 0 && vi->ntxq > 1) vi->rsrv_noflowq = iaq.rsrv_noflowq ? 1 : 0; else vi->rsrv_noflowq = 0; #ifdef TCP_OFFLOAD vi->first_ofld_rxq = ofld_rqidx; vi->first_ofld_txq = ofld_tqidx; if (port_top_speed(pi) >= 10) { vi->flags |= iaq.intr_flags_10g & INTR_OFLD_RXQ; vi->nofldrxq = j == 0 ? iaq.nofldrxq10g : iaq.nofldrxq_vi; vi->nofldtxq = j == 0 ? iaq.nofldtxq10g : iaq.nofldtxq_vi; } else { vi->flags |= iaq.intr_flags_1g & INTR_OFLD_RXQ; vi->nofldrxq = j == 0 ? iaq.nofldrxq1g : iaq.nofldrxq_vi; vi->nofldtxq = j == 0 ? iaq.nofldtxq1g : iaq.nofldtxq_vi; } ofld_rqidx += vi->nofldrxq; ofld_tqidx += vi->nofldtxq; #endif #ifdef DEV_NETMAP if (j > 0) { vi->first_nm_rxq = nm_rqidx; vi->first_nm_txq = nm_tqidx; vi->nnmrxq = iaq.nnmrxq_vi; vi->nnmtxq = iaq.nnmtxq_vi; nm_rqidx += vi->nnmrxq; nm_tqidx += vi->nnmtxq; } #endif } } rc = t4_setup_intr_handlers(sc); if (rc != 0) { device_printf(dev, "failed to setup interrupt handlers: %d\n", rc); goto done; } rc = bus_generic_probe(dev); if (rc != 0) { device_printf(dev, "failed to probe child drivers: %d\n", rc); goto done; } rc = bus_generic_attach(dev); if (rc != 0) { device_printf(dev, "failed to attach all child ports: %d\n", rc); goto done; } device_printf(dev, "PCIe gen%d x%d, %d ports, %d %s interrupt%s, %d eq, %d iq\n", sc->params.pci.speed, sc->params.pci.width, sc->params.nports, sc->intr_count, sc->intr_type == INTR_MSIX ? "MSI-X" : (sc->intr_type == INTR_MSI ? "MSI" : "INTx"), sc->intr_count > 1 ? "s" : "", sc->sge.neq, sc->sge.niq); t4_set_desc(sc); notify_siblings(dev, 0); done: if (rc != 0 && sc->cdev) { /* cdev was created and so cxgbetool works; recover that way. */ device_printf(dev, "error during attach, adapter is now in recovery mode.\n"); rc = 0; } if (rc != 0) t4_detach_common(dev); else t4_sysctls(sc); return (rc); } static int t4_ready(device_t dev) { struct adapter *sc; sc = device_get_softc(dev); if (sc->flags & FW_OK) return (0); return (ENXIO); } static int t4_read_port_device(device_t dev, int port, device_t *child) { struct adapter *sc; struct port_info *pi; sc = device_get_softc(dev); if (port < 0 || port >= MAX_NPORTS) return (EINVAL); pi = sc->port[port]; if (pi == NULL || pi->dev == NULL) return (ENXIO); *child = pi->dev; return (0); } static int notify_siblings(device_t dev, int detaching) { device_t sibling; int error, i; error = 0; for (i = 0; i < PCI_FUNCMAX; i++) { if (i == pci_get_function(dev)) continue; sibling = pci_find_dbsf(pci_get_domain(dev), pci_get_bus(dev), pci_get_slot(dev), i); if (sibling == NULL || !device_is_attached(sibling)) continue; if (detaching) error = T4_DETACH_CHILD(sibling); else (void)T4_ATTACH_CHILD(sibling); if (error) break; } return (error); } /* * Idempotent */ static int t4_detach(device_t dev) { struct adapter *sc; int rc; sc = device_get_softc(dev); rc = notify_siblings(dev, 1); if (rc) { device_printf(dev, "failed to detach sibling devices: %d\n", rc); return (rc); } return (t4_detach_common(dev)); } int t4_detach_common(device_t dev) { struct adapter *sc; struct port_info *pi; int i, rc; sc = device_get_softc(dev); if (sc->flags & FULL_INIT_DONE) { if (!(sc->flags & IS_VF)) t4_intr_disable(sc); } if (sc->cdev) { destroy_dev(sc->cdev); sc->cdev = NULL; } if (device_is_attached(dev)) { rc = bus_generic_detach(dev); if (rc) { device_printf(dev, "failed to detach child devices: %d\n", rc); return (rc); } } for (i = 0; i < sc->intr_count; i++) t4_free_irq(sc, &sc->irq[i]); if ((sc->flags & (IS_VF | FW_OK)) == FW_OK) t4_free_tx_sched(sc); for (i = 0; i < MAX_NPORTS; i++) { pi = sc->port[i]; if (pi) { t4_free_vi(sc, sc->mbox, sc->pf, 0, pi->vi[0].viid); if (pi->dev) device_delete_child(dev, pi->dev); mtx_destroy(&pi->pi_lock); free(pi->vi, M_CXGBE); free(pi, M_CXGBE); } } device_delete_children(dev); if (sc->flags & FULL_INIT_DONE) adapter_full_uninit(sc); if ((sc->flags & (IS_VF | FW_OK)) == FW_OK) t4_fw_bye(sc, sc->mbox); if (sc->intr_type == INTR_MSI || sc->intr_type == INTR_MSIX) pci_release_msi(dev); if (sc->regs_res) bus_release_resource(dev, SYS_RES_MEMORY, sc->regs_rid, sc->regs_res); if (sc->udbs_res) bus_release_resource(dev, SYS_RES_MEMORY, sc->udbs_rid, sc->udbs_res); if (sc->msix_res) bus_release_resource(dev, SYS_RES_MEMORY, sc->msix_rid, sc->msix_res); if (sc->l2t) t4_free_l2t(sc->l2t); #ifdef TCP_OFFLOAD free(sc->sge.ofld_rxq, M_CXGBE); free(sc->sge.ofld_txq, M_CXGBE); #endif #ifdef DEV_NETMAP free(sc->sge.nm_rxq, M_CXGBE); free(sc->sge.nm_txq, M_CXGBE); #endif free(sc->irq, M_CXGBE); free(sc->sge.rxq, M_CXGBE); free(sc->sge.txq, M_CXGBE); free(sc->sge.ctrlq, M_CXGBE); free(sc->sge.iqmap, M_CXGBE); free(sc->sge.eqmap, M_CXGBE); free(sc->tids.ftid_tab, M_CXGBE); t4_destroy_dma_tag(sc); if (mtx_initialized(&sc->sc_lock)) { sx_xlock(&t4_list_lock); SLIST_REMOVE(&t4_list, sc, adapter, link); sx_xunlock(&t4_list_lock); mtx_destroy(&sc->sc_lock); } callout_drain(&sc->sfl_callout); if (mtx_initialized(&sc->tids.ftid_lock)) mtx_destroy(&sc->tids.ftid_lock); if (mtx_initialized(&sc->sfl_lock)) mtx_destroy(&sc->sfl_lock); if (mtx_initialized(&sc->ifp_lock)) mtx_destroy(&sc->ifp_lock); if (mtx_initialized(&sc->reg_lock)) mtx_destroy(&sc->reg_lock); for (i = 0; i < NUM_MEMWIN; i++) { struct memwin *mw = &sc->memwin[i]; if (rw_initialized(&mw->mw_lock)) rw_destroy(&mw->mw_lock); } bzero(sc, sizeof(*sc)); return (0); } static int cxgbe_probe(device_t dev) { char buf[128]; struct port_info *pi = device_get_softc(dev); snprintf(buf, sizeof(buf), "port %d", pi->port_id); device_set_desc_copy(dev, buf); return (BUS_PROBE_DEFAULT); } #define T4_CAP (IFCAP_VLAN_HWTAGGING | IFCAP_VLAN_MTU | IFCAP_HWCSUM | \ IFCAP_VLAN_HWCSUM | IFCAP_TSO | IFCAP_JUMBO_MTU | IFCAP_LRO | \ IFCAP_VLAN_HWTSO | IFCAP_LINKSTATE | IFCAP_HWCSUM_IPV6 | IFCAP_HWSTATS) #define T4_CAP_ENABLE (T4_CAP) static int cxgbe_vi_attach(device_t dev, struct vi_info *vi) { struct ifnet *ifp; struct sbuf *sb; vi->xact_addr_filt = -1; callout_init(&vi->tick, 1); /* Allocate an ifnet and set it up */ ifp = if_alloc(IFT_ETHER); if (ifp == NULL) { device_printf(dev, "Cannot allocate ifnet\n"); return (ENOMEM); } vi->ifp = ifp; ifp->if_softc = vi; if_initname(ifp, device_get_name(dev), device_get_unit(dev)); ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX | IFF_MULTICAST; ifp->if_init = cxgbe_init; ifp->if_ioctl = cxgbe_ioctl; ifp->if_transmit = cxgbe_transmit; ifp->if_qflush = cxgbe_qflush; ifp->if_get_counter = cxgbe_get_counter; ifp->if_capabilities = T4_CAP; #ifdef TCP_OFFLOAD if (vi->nofldrxq != 0) ifp->if_capabilities |= IFCAP_TOE; #endif #ifdef DEV_NETMAP if (vi->nnmrxq != 0) ifp->if_capabilities |= IFCAP_NETMAP; #endif ifp->if_capenable = T4_CAP_ENABLE; ifp->if_hwassist = CSUM_TCP | CSUM_UDP | CSUM_IP | CSUM_TSO | CSUM_UDP_IPV6 | CSUM_TCP_IPV6; ifp->if_hw_tsomax = 65536 - (ETHER_HDR_LEN + ETHER_VLAN_ENCAP_LEN); ifp->if_hw_tsomaxsegcount = TX_SGL_SEGS; ifp->if_hw_tsomaxsegsize = 65536; /* Initialize ifmedia for this VI */ ifmedia_init(&vi->media, IFM_IMASK, cxgbe_media_change, cxgbe_media_status); vi->vlan_c = EVENTHANDLER_REGISTER(vlan_config, cxgbe_vlan_config, ifp, EVENTHANDLER_PRI_ANY); ether_ifattach(ifp, vi->hw_addr); #ifdef DEV_NETMAP if (ifp->if_capabilities & IFCAP_NETMAP) cxgbe_nm_attach(vi); #endif sb = sbuf_new_auto(); sbuf_printf(sb, "%d txq, %d rxq (NIC)", vi->ntxq, vi->nrxq); #ifdef TCP_OFFLOAD if (ifp->if_capabilities & IFCAP_TOE) sbuf_printf(sb, "; %d txq, %d rxq (TOE)", vi->nofldtxq, vi->nofldrxq); #endif #ifdef DEV_NETMAP if (ifp->if_capabilities & IFCAP_NETMAP) sbuf_printf(sb, "; %d txq, %d rxq (netmap)", vi->nnmtxq, vi->nnmrxq); #endif sbuf_finish(sb); device_printf(dev, "%s\n", sbuf_data(sb)); sbuf_delete(sb); vi_sysctls(vi); return (0); } static int cxgbe_attach(device_t dev) { struct port_info *pi = device_get_softc(dev); struct adapter *sc = pi->adapter; struct vi_info *vi; int i, rc; callout_init_mtx(&pi->tick, &pi->pi_lock, 0); rc = cxgbe_vi_attach(dev, &pi->vi[0]); if (rc) return (rc); for_each_vi(pi, i, vi) { if (i == 0) continue; vi->dev = device_add_child(dev, sc->names->vi_ifnet_name, -1); if (vi->dev == NULL) { device_printf(dev, "failed to add VI %d\n", i); continue; } device_set_softc(vi->dev, vi); } cxgbe_sysctls(pi); bus_generic_attach(dev); return (0); } static void cxgbe_vi_detach(struct vi_info *vi) { struct ifnet *ifp = vi->ifp; ether_ifdetach(ifp); if (vi->vlan_c) EVENTHANDLER_DEREGISTER(vlan_config, vi->vlan_c); /* Let detach proceed even if these fail. */ #ifdef DEV_NETMAP if (ifp->if_capabilities & IFCAP_NETMAP) cxgbe_nm_detach(vi); #endif cxgbe_uninit_synchronized(vi); callout_drain(&vi->tick); vi_full_uninit(vi); ifmedia_removeall(&vi->media); if_free(vi->ifp); vi->ifp = NULL; } static int cxgbe_detach(device_t dev) { struct port_info *pi = device_get_softc(dev); struct adapter *sc = pi->adapter; int rc; /* Detach the extra VIs first. */ rc = bus_generic_detach(dev); if (rc) return (rc); device_delete_children(dev); doom_vi(sc, &pi->vi[0]); if (pi->flags & HAS_TRACEQ) { sc->traceq = -1; /* cloner should not create ifnet */ t4_tracer_port_detach(sc); } cxgbe_vi_detach(&pi->vi[0]); callout_drain(&pi->tick); end_synchronized_op(sc, 0); return (0); } static void cxgbe_init(void *arg) { struct vi_info *vi = arg; struct adapter *sc = vi->pi->adapter; if (begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4init") != 0) return; cxgbe_init_synchronized(vi); end_synchronized_op(sc, 0); } static int cxgbe_ioctl(struct ifnet *ifp, unsigned long cmd, caddr_t data) { int rc = 0, mtu, flags, can_sleep; struct vi_info *vi = ifp->if_softc; struct adapter *sc = vi->pi->adapter; struct ifreq *ifr = (struct ifreq *)data; uint32_t mask; switch (cmd) { case SIOCSIFMTU: mtu = ifr->ifr_mtu; if (mtu < ETHERMIN || mtu > MAX_MTU) return (EINVAL); rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4mtu"); if (rc) return (rc); ifp->if_mtu = mtu; if (vi->flags & VI_INIT_DONE) { t4_update_fl_bufsize(ifp); if (ifp->if_drv_flags & IFF_DRV_RUNNING) rc = update_mac_settings(ifp, XGMAC_MTU); } end_synchronized_op(sc, 0); break; case SIOCSIFFLAGS: can_sleep = 0; redo_sifflags: rc = begin_synchronized_op(sc, vi, can_sleep ? (SLEEP_OK | INTR_OK) : HOLD_LOCK, "t4flg"); if (rc) return (rc); if (ifp->if_flags & IFF_UP) { if (ifp->if_drv_flags & IFF_DRV_RUNNING) { flags = vi->if_flags; if ((ifp->if_flags ^ flags) & (IFF_PROMISC | IFF_ALLMULTI)) { if (can_sleep == 1) { end_synchronized_op(sc, 0); can_sleep = 0; goto redo_sifflags; } rc = update_mac_settings(ifp, XGMAC_PROMISC | XGMAC_ALLMULTI); } } else { if (can_sleep == 0) { end_synchronized_op(sc, LOCK_HELD); can_sleep = 1; goto redo_sifflags; } rc = cxgbe_init_synchronized(vi); } vi->if_flags = ifp->if_flags; } else if (ifp->if_drv_flags & IFF_DRV_RUNNING) { if (can_sleep == 0) { end_synchronized_op(sc, LOCK_HELD); can_sleep = 1; goto redo_sifflags; } rc = cxgbe_uninit_synchronized(vi); } end_synchronized_op(sc, can_sleep ? 0 : LOCK_HELD); break; case SIOCADDMULTI: case SIOCDELMULTI: /* these two are called with a mutex held :-( */ rc = begin_synchronized_op(sc, vi, HOLD_LOCK, "t4multi"); if (rc) return (rc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) rc = update_mac_settings(ifp, XGMAC_MCADDRS); end_synchronized_op(sc, LOCK_HELD); break; case SIOCSIFCAP: rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4cap"); if (rc) return (rc); mask = ifr->ifr_reqcap ^ ifp->if_capenable; if (mask & IFCAP_TXCSUM) { ifp->if_capenable ^= IFCAP_TXCSUM; ifp->if_hwassist ^= (CSUM_TCP | CSUM_UDP | CSUM_IP); if (IFCAP_TSO4 & ifp->if_capenable && !(IFCAP_TXCSUM & ifp->if_capenable)) { ifp->if_capenable &= ~IFCAP_TSO4; if_printf(ifp, "tso4 disabled due to -txcsum.\n"); } } if (mask & IFCAP_TXCSUM_IPV6) { ifp->if_capenable ^= IFCAP_TXCSUM_IPV6; ifp->if_hwassist ^= (CSUM_UDP_IPV6 | CSUM_TCP_IPV6); if (IFCAP_TSO6 & ifp->if_capenable && !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) { ifp->if_capenable &= ~IFCAP_TSO6; if_printf(ifp, "tso6 disabled due to -txcsum6.\n"); } } if (mask & IFCAP_RXCSUM) ifp->if_capenable ^= IFCAP_RXCSUM; if (mask & IFCAP_RXCSUM_IPV6) ifp->if_capenable ^= IFCAP_RXCSUM_IPV6; /* * Note that we leave CSUM_TSO alone (it is always set). The * kernel takes both IFCAP_TSOx and CSUM_TSO into account before * sending a TSO request our way, so it's sufficient to toggle * IFCAP_TSOx only. */ if (mask & IFCAP_TSO4) { if (!(IFCAP_TSO4 & ifp->if_capenable) && !(IFCAP_TXCSUM & ifp->if_capenable)) { if_printf(ifp, "enable txcsum first.\n"); rc = EAGAIN; goto fail; } ifp->if_capenable ^= IFCAP_TSO4; } if (mask & IFCAP_TSO6) { if (!(IFCAP_TSO6 & ifp->if_capenable) && !(IFCAP_TXCSUM_IPV6 & ifp->if_capenable)) { if_printf(ifp, "enable txcsum6 first.\n"); rc = EAGAIN; goto fail; } ifp->if_capenable ^= IFCAP_TSO6; } if (mask & IFCAP_LRO) { #if defined(INET) || defined(INET6) int i; struct sge_rxq *rxq; ifp->if_capenable ^= IFCAP_LRO; for_each_rxq(vi, i, rxq) { if (ifp->if_capenable & IFCAP_LRO) rxq->iq.flags |= IQ_LRO_ENABLED; else rxq->iq.flags &= ~IQ_LRO_ENABLED; } #endif } #ifdef TCP_OFFLOAD if (mask & IFCAP_TOE) { int enable = (ifp->if_capenable ^ mask) & IFCAP_TOE; rc = toe_capability(vi, enable); if (rc != 0) goto fail; ifp->if_capenable ^= mask; } #endif if (mask & IFCAP_VLAN_HWTAGGING) { ifp->if_capenable ^= IFCAP_VLAN_HWTAGGING; if (ifp->if_drv_flags & IFF_DRV_RUNNING) rc = update_mac_settings(ifp, XGMAC_VLANEX); } if (mask & IFCAP_VLAN_MTU) { ifp->if_capenable ^= IFCAP_VLAN_MTU; /* Need to find out how to disable auto-mtu-inflation */ } if (mask & IFCAP_VLAN_HWTSO) ifp->if_capenable ^= IFCAP_VLAN_HWTSO; if (mask & IFCAP_VLAN_HWCSUM) ifp->if_capenable ^= IFCAP_VLAN_HWCSUM; #ifdef VLAN_CAPABILITIES VLAN_CAPABILITIES(ifp); #endif fail: end_synchronized_op(sc, 0); break; case SIOCSIFMEDIA: case SIOCGIFMEDIA: case SIOCGIFXMEDIA: ifmedia_ioctl(ifp, ifr, &vi->media, cmd); break; case SIOCGI2C: { struct ifi2creq i2c; rc = copyin(ifr->ifr_data, &i2c, sizeof(i2c)); if (rc != 0) break; if (i2c.dev_addr != 0xA0 && i2c.dev_addr != 0xA2) { rc = EPERM; break; } if (i2c.len > sizeof(i2c.data)) { rc = EINVAL; break; } rc = begin_synchronized_op(sc, vi, SLEEP_OK | INTR_OK, "t4i2c"); if (rc) return (rc); rc = -t4_i2c_rd(sc, sc->mbox, vi->pi->port_id, i2c.dev_addr, i2c.offset, i2c.len, &i2c.data[0]); end_synchronized_op(sc, 0); if (rc == 0) rc = copyout(&i2c, ifr->ifr_data, sizeof(i2c)); break; } default: rc = ether_ioctl(ifp, cmd, data); } return (rc); } static int cxgbe_transmit(struct ifnet *ifp, struct mbuf *m) { struct vi_info *vi = ifp->if_softc; struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; struct sge_txq *txq; void *items[1]; int rc; M_ASSERTPKTHDR(m); MPASS(m->m_nextpkt == NULL); /* not quite ready for this yet */ if (__predict_false(pi->link_cfg.link_ok == 0)) { m_freem(m); return (ENETDOWN); } rc = parse_pkt(sc, &m); if (__predict_false(rc != 0)) { MPASS(m == NULL); /* was freed already */ atomic_add_int(&pi->tx_parse_error, 1); /* rare, atomic is ok */ return (rc); } /* Select a txq. */ txq = &sc->sge.txq[vi->first_txq]; if (M_HASHTYPE_GET(m) != M_HASHTYPE_NONE) txq += ((m->m_pkthdr.flowid % (vi->ntxq - vi->rsrv_noflowq)) + vi->rsrv_noflowq); items[0] = m; rc = mp_ring_enqueue(txq->r, items, 1, 4096); if (__predict_false(rc != 0)) m_freem(m); return (rc); } static void cxgbe_qflush(struct ifnet *ifp) { struct vi_info *vi = ifp->if_softc; struct sge_txq *txq; int i; /* queues do not exist if !VI_INIT_DONE. */ if (vi->flags & VI_INIT_DONE) { for_each_txq(vi, i, txq) { TXQ_LOCK(txq); txq->eq.flags |= EQ_QFLUSH; TXQ_UNLOCK(txq); while (!mp_ring_is_idle(txq->r)) { mp_ring_check_drainage(txq->r, 0); pause("qflush", 1); } TXQ_LOCK(txq); txq->eq.flags &= ~EQ_QFLUSH; TXQ_UNLOCK(txq); } } if_qflush(ifp); } static uint64_t vi_get_counter(struct ifnet *ifp, ift_counter c) { struct vi_info *vi = ifp->if_softc; struct fw_vi_stats_vf *s = &vi->stats; vi_refresh_stats(vi->pi->adapter, vi); switch (c) { case IFCOUNTER_IPACKETS: return (s->rx_bcast_frames + s->rx_mcast_frames + s->rx_ucast_frames); case IFCOUNTER_IERRORS: return (s->rx_err_frames); case IFCOUNTER_OPACKETS: return (s->tx_bcast_frames + s->tx_mcast_frames + s->tx_ucast_frames + s->tx_offload_frames); case IFCOUNTER_OERRORS: return (s->tx_drop_frames); case IFCOUNTER_IBYTES: return (s->rx_bcast_bytes + s->rx_mcast_bytes + s->rx_ucast_bytes); case IFCOUNTER_OBYTES: return (s->tx_bcast_bytes + s->tx_mcast_bytes + s->tx_ucast_bytes + s->tx_offload_bytes); case IFCOUNTER_IMCASTS: return (s->rx_mcast_frames); case IFCOUNTER_OMCASTS: return (s->tx_mcast_frames); case IFCOUNTER_OQDROPS: { uint64_t drops; drops = 0; if (vi->flags & VI_INIT_DONE) { int i; struct sge_txq *txq; for_each_txq(vi, i, txq) drops += counter_u64_fetch(txq->r->drops); } return (drops); } default: return (if_get_counter_default(ifp, c)); } } uint64_t cxgbe_get_counter(struct ifnet *ifp, ift_counter c) { struct vi_info *vi = ifp->if_softc; struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; struct port_stats *s = &pi->stats; if (pi->nvi > 1 || sc->flags & IS_VF) return (vi_get_counter(ifp, c)); cxgbe_refresh_stats(sc, pi); switch (c) { case IFCOUNTER_IPACKETS: return (s->rx_frames); case IFCOUNTER_IERRORS: return (s->rx_jabber + s->rx_runt + s->rx_too_long + s->rx_fcs_err + s->rx_len_err); case IFCOUNTER_OPACKETS: return (s->tx_frames); case IFCOUNTER_OERRORS: return (s->tx_error_frames); case IFCOUNTER_IBYTES: return (s->rx_octets); case IFCOUNTER_OBYTES: return (s->tx_octets); case IFCOUNTER_IMCASTS: return (s->rx_mcast_frames); case IFCOUNTER_OMCASTS: return (s->tx_mcast_frames); case IFCOUNTER_IQDROPS: return (s->rx_ovflow0 + s->rx_ovflow1 + s->rx_ovflow2 + s->rx_ovflow3 + s->rx_trunc0 + s->rx_trunc1 + s->rx_trunc2 + s->rx_trunc3 + pi->tnl_cong_drops); case IFCOUNTER_OQDROPS: { uint64_t drops; drops = s->tx_drop; if (vi->flags & VI_INIT_DONE) { int i; struct sge_txq *txq; for_each_txq(vi, i, txq) drops += counter_u64_fetch(txq->r->drops); } return (drops); } default: return (if_get_counter_default(ifp, c)); } } static int cxgbe_media_change(struct ifnet *ifp) { struct vi_info *vi = ifp->if_softc; device_printf(vi->dev, "%s unimplemented.\n", __func__); return (EOPNOTSUPP); } static void cxgbe_media_status(struct ifnet *ifp, struct ifmediareq *ifmr) { struct vi_info *vi = ifp->if_softc; struct port_info *pi = vi->pi; struct ifmedia_entry *cur; struct link_config *lc = &pi->link_cfg; /* * If all the interfaces are administratively down the firmware does not * report transceiver changes. Refresh port info here so that ifconfig * displays accurate information at all times. */ if (begin_synchronized_op(pi->adapter, NULL, SLEEP_OK | INTR_OK, "t4med") == 0) { PORT_LOCK(pi); if (pi->up_vis == 0) { t4_update_port_info(pi); build_medialist(pi, &vi->media); } PORT_UNLOCK(pi); end_synchronized_op(pi->adapter, 0); } cur = vi->media.ifm_cur; ifmr->ifm_status = IFM_AVALID; if (lc->link_ok == 0) return; ifmr->ifm_status |= IFM_ACTIVE; ifmr->ifm_active &= ~(IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE); if (lc->fc & PAUSE_RX) ifmr->ifm_active |= IFM_ETH_RXPAUSE; if (lc->fc & PAUSE_TX) ifmr->ifm_active |= IFM_ETH_TXPAUSE; /* active and current will differ iff current media is autoselect. */ if (IFM_SUBTYPE(cur->ifm_media) != IFM_AUTO) return; ifmr->ifm_active = IFM_ETHER | IFM_FDX; if (lc->fc & PAUSE_RX) ifmr->ifm_active |= IFM_ETH_RXPAUSE; if (lc->fc & PAUSE_TX) ifmr->ifm_active |= IFM_ETH_TXPAUSE; switch (lc->speed) { case 10000: ifmr->ifm_active |= IFM_10G_T; break; case 1000: ifmr->ifm_active |= IFM_1000_T; break; case 100: ifmr->ifm_active |= IFM_100_TX; break; case 10: ifmr->ifm_active |= IFM_10_T; break; default: device_printf(vi->dev, "link up but speed unknown (%u)\n", lc->speed); } } static int vcxgbe_probe(device_t dev) { char buf[128]; struct vi_info *vi = device_get_softc(dev); snprintf(buf, sizeof(buf), "port %d vi %td", vi->pi->port_id, vi - vi->pi->vi); device_set_desc_copy(dev, buf); return (BUS_PROBE_DEFAULT); } static int vcxgbe_attach(device_t dev) { struct vi_info *vi; struct port_info *pi; struct adapter *sc; int func, index, rc; u32 param, val; vi = device_get_softc(dev); pi = vi->pi; sc = pi->adapter; index = vi - pi->vi; KASSERT(index < nitems(vi_mac_funcs), ("%s: VI %s doesn't have a MAC func", __func__, device_get_nameunit(dev))); func = vi_mac_funcs[index]; rc = t4_alloc_vi_func(sc, sc->mbox, pi->tx_chan, sc->pf, 0, 1, vi->hw_addr, &vi->rss_size, func, 0); if (rc < 0) { device_printf(dev, "Failed to allocate virtual interface " "for port %d: %d\n", pi->port_id, -rc); return (-rc); } vi->viid = rc; if (chip_id(sc) <= CHELSIO_T5) vi->smt_idx = (rc & 0x7f) << 1; else vi->smt_idx = (rc & 0x7f); param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_RSSINFO) | V_FW_PARAMS_PARAM_YZ(vi->viid); rc = t4_query_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); if (rc) vi->rss_base = 0xffff; else { /* MPASS((val >> 16) == rss_size); */ vi->rss_base = val & 0xffff; } rc = cxgbe_vi_attach(dev, vi); if (rc) { t4_free_vi(sc, sc->mbox, sc->pf, 0, vi->viid); return (rc); } return (0); } static int vcxgbe_detach(device_t dev) { struct vi_info *vi; struct adapter *sc; vi = device_get_softc(dev); sc = vi->pi->adapter; doom_vi(sc, vi); cxgbe_vi_detach(vi); t4_free_vi(sc, sc->mbox, sc->pf, 0, vi->viid); end_synchronized_op(sc, 0); return (0); } void t4_fatal_err(struct adapter *sc) { t4_set_reg_field(sc, A_SGE_CONTROL, F_GLOBALENABLE, 0); t4_intr_disable(sc); log(LOG_EMERG, "%s: encountered fatal error, adapter stopped.\n", device_get_nameunit(sc->dev)); } void t4_add_adapter(struct adapter *sc) { sx_xlock(&t4_list_lock); SLIST_INSERT_HEAD(&t4_list, sc, link); sx_xunlock(&t4_list_lock); } int t4_map_bars_0_and_4(struct adapter *sc) { sc->regs_rid = PCIR_BAR(0); sc->regs_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &sc->regs_rid, RF_ACTIVE); if (sc->regs_res == NULL) { device_printf(sc->dev, "cannot map registers.\n"); return (ENXIO); } sc->bt = rman_get_bustag(sc->regs_res); sc->bh = rman_get_bushandle(sc->regs_res); sc->mmio_len = rman_get_size(sc->regs_res); setbit(&sc->doorbells, DOORBELL_KDB); sc->msix_rid = PCIR_BAR(4); sc->msix_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &sc->msix_rid, RF_ACTIVE); if (sc->msix_res == NULL) { device_printf(sc->dev, "cannot map MSI-X BAR.\n"); return (ENXIO); } return (0); } int t4_map_bar_2(struct adapter *sc) { /* * T4: only iWARP driver uses the userspace doorbells. There is no need * to map it if RDMA is disabled. */ if (is_t4(sc) && sc->rdmacaps == 0) return (0); sc->udbs_rid = PCIR_BAR(2); sc->udbs_res = bus_alloc_resource_any(sc->dev, SYS_RES_MEMORY, &sc->udbs_rid, RF_ACTIVE); if (sc->udbs_res == NULL) { device_printf(sc->dev, "cannot map doorbell BAR.\n"); return (ENXIO); } sc->udbs_base = rman_get_virtual(sc->udbs_res); if (chip_id(sc) >= CHELSIO_T5) { setbit(&sc->doorbells, DOORBELL_UDB); #if defined(__i386__) || defined(__amd64__) if (t5_write_combine) { int rc, mode; /* * Enable write combining on BAR2. This is the * userspace doorbell BAR and is split into 128B * (UDBS_SEG_SIZE) doorbell regions, each associated * with an egress queue. The first 64B has the doorbell * and the second 64B can be used to submit a tx work * request with an implicit doorbell. */ rc = pmap_change_attr((vm_offset_t)sc->udbs_base, rman_get_size(sc->udbs_res), PAT_WRITE_COMBINING); if (rc == 0) { clrbit(&sc->doorbells, DOORBELL_UDB); setbit(&sc->doorbells, DOORBELL_WCWR); setbit(&sc->doorbells, DOORBELL_UDBWC); } else { device_printf(sc->dev, "couldn't enable write combining: %d\n", rc); } mode = is_t5(sc) ? V_STATMODE(0) : V_T6_STATMODE(0); t4_write_reg(sc, A_SGE_STAT_CFG, V_STATSOURCE_T5(7) | mode); } #endif } return (0); } struct memwin_init { uint32_t base; uint32_t aperture; }; static const struct memwin_init t4_memwin[NUM_MEMWIN] = { { MEMWIN0_BASE, MEMWIN0_APERTURE }, { MEMWIN1_BASE, MEMWIN1_APERTURE }, { MEMWIN2_BASE_T4, MEMWIN2_APERTURE_T4 } }; static const struct memwin_init t5_memwin[NUM_MEMWIN] = { { MEMWIN0_BASE, MEMWIN0_APERTURE }, { MEMWIN1_BASE, MEMWIN1_APERTURE }, { MEMWIN2_BASE_T5, MEMWIN2_APERTURE_T5 }, }; static void setup_memwin(struct adapter *sc) { const struct memwin_init *mw_init; struct memwin *mw; int i; uint32_t bar0; if (is_t4(sc)) { /* * Read low 32b of bar0 indirectly via the hardware backdoor * mechanism. Works from within PCI passthrough environments * too, where rman_get_start() can return a different value. We * need to program the T4 memory window decoders with the actual * addresses that will be coming across the PCIe link. */ bar0 = t4_hw_pci_read_cfg4(sc, PCIR_BAR(0)); bar0 &= (uint32_t) PCIM_BAR_MEM_BASE; mw_init = &t4_memwin[0]; } else { /* T5+ use the relative offset inside the PCIe BAR */ bar0 = 0; mw_init = &t5_memwin[0]; } for (i = 0, mw = &sc->memwin[0]; i < NUM_MEMWIN; i++, mw_init++, mw++) { rw_init(&mw->mw_lock, "memory window access"); mw->mw_base = mw_init->base; mw->mw_aperture = mw_init->aperture; mw->mw_curpos = 0; t4_write_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, i), (mw->mw_base + bar0) | V_BIR(0) | V_WINDOW(ilog2(mw->mw_aperture) - 10)); rw_wlock(&mw->mw_lock); position_memwin(sc, i, 0); rw_wunlock(&mw->mw_lock); } /* flush */ t4_read_reg(sc, PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_BASE_WIN, 2)); } /* * Positions the memory window at the given address in the card's address space. * There are some alignment requirements and the actual position may be at an * address prior to the requested address. mw->mw_curpos always has the actual * position of the window. */ static void position_memwin(struct adapter *sc, int idx, uint32_t addr) { struct memwin *mw; uint32_t pf; uint32_t reg; MPASS(idx >= 0 && idx < NUM_MEMWIN); mw = &sc->memwin[idx]; rw_assert(&mw->mw_lock, RA_WLOCKED); if (is_t4(sc)) { pf = 0; mw->mw_curpos = addr & ~0xf; /* start must be 16B aligned */ } else { pf = V_PFNUM(sc->pf); mw->mw_curpos = addr & ~0x7f; /* start must be 128B aligned */ } reg = PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, idx); t4_write_reg(sc, reg, mw->mw_curpos | pf); t4_read_reg(sc, reg); /* flush */ } static int rw_via_memwin(struct adapter *sc, int idx, uint32_t addr, uint32_t *val, int len, int rw) { struct memwin *mw; uint32_t mw_end, v; MPASS(idx >= 0 && idx < NUM_MEMWIN); /* Memory can only be accessed in naturally aligned 4 byte units */ if (addr & 3 || len & 3 || len <= 0) return (EINVAL); mw = &sc->memwin[idx]; while (len > 0) { rw_rlock(&mw->mw_lock); mw_end = mw->mw_curpos + mw->mw_aperture; if (addr >= mw_end || addr < mw->mw_curpos) { /* Will need to reposition the window */ if (!rw_try_upgrade(&mw->mw_lock)) { rw_runlock(&mw->mw_lock); rw_wlock(&mw->mw_lock); } rw_assert(&mw->mw_lock, RA_WLOCKED); position_memwin(sc, idx, addr); rw_downgrade(&mw->mw_lock); mw_end = mw->mw_curpos + mw->mw_aperture; } rw_assert(&mw->mw_lock, RA_RLOCKED); while (addr < mw_end && len > 0) { if (rw == 0) { v = t4_read_reg(sc, mw->mw_base + addr - mw->mw_curpos); *val++ = le32toh(v); } else { v = *val++; t4_write_reg(sc, mw->mw_base + addr - mw->mw_curpos, htole32(v)); } addr += 4; len -= 4; } rw_runlock(&mw->mw_lock); } return (0); } static inline int read_via_memwin(struct adapter *sc, int idx, uint32_t addr, uint32_t *val, int len) { return (rw_via_memwin(sc, idx, addr, val, len, 0)); } static inline int write_via_memwin(struct adapter *sc, int idx, uint32_t addr, const uint32_t *val, int len) { return (rw_via_memwin(sc, idx, addr, (void *)(uintptr_t)val, len, 1)); } static int t4_range_cmp(const void *a, const void *b) { return ((const struct t4_range *)a)->start - ((const struct t4_range *)b)->start; } /* * Verify that the memory range specified by the addr/len pair is valid within * the card's address space. */ static int validate_mem_range(struct adapter *sc, uint32_t addr, int len) { struct t4_range mem_ranges[4], *r, *next; uint32_t em, addr_len; int i, n, remaining; /* Memory can only be accessed in naturally aligned 4 byte units */ if (addr & 3 || len & 3 || len <= 0) return (EINVAL); /* Enabled memories */ em = t4_read_reg(sc, A_MA_TARGET_MEM_ENABLE); r = &mem_ranges[0]; n = 0; bzero(r, sizeof(mem_ranges)); if (em & F_EDRAM0_ENABLE) { addr_len = t4_read_reg(sc, A_MA_EDRAM0_BAR); r->size = G_EDRAM0_SIZE(addr_len) << 20; if (r->size > 0) { r->start = G_EDRAM0_BASE(addr_len) << 20; if (addr >= r->start && addr + len <= r->start + r->size) return (0); r++; n++; } } if (em & F_EDRAM1_ENABLE) { addr_len = t4_read_reg(sc, A_MA_EDRAM1_BAR); r->size = G_EDRAM1_SIZE(addr_len) << 20; if (r->size > 0) { r->start = G_EDRAM1_BASE(addr_len) << 20; if (addr >= r->start && addr + len <= r->start + r->size) return (0); r++; n++; } } if (em & F_EXT_MEM_ENABLE) { addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY_BAR); r->size = G_EXT_MEM_SIZE(addr_len) << 20; if (r->size > 0) { r->start = G_EXT_MEM_BASE(addr_len) << 20; if (addr >= r->start && addr + len <= r->start + r->size) return (0); r++; n++; } } if (is_t5(sc) && em & F_EXT_MEM1_ENABLE) { addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY1_BAR); r->size = G_EXT_MEM1_SIZE(addr_len) << 20; if (r->size > 0) { r->start = G_EXT_MEM1_BASE(addr_len) << 20; if (addr >= r->start && addr + len <= r->start + r->size) return (0); r++; n++; } } MPASS(n <= nitems(mem_ranges)); if (n > 1) { /* Sort and merge the ranges. */ qsort(mem_ranges, n, sizeof(struct t4_range), t4_range_cmp); /* Start from index 0 and examine the next n - 1 entries. */ r = &mem_ranges[0]; for (remaining = n - 1; remaining > 0; remaining--, r++) { MPASS(r->size > 0); /* r is a valid entry. */ next = r + 1; MPASS(next->size > 0); /* and so is the next one. */ while (r->start + r->size >= next->start) { /* Merge the next one into the current entry. */ r->size = max(r->start + r->size, next->start + next->size) - r->start; n--; /* One fewer entry in total. */ if (--remaining == 0) goto done; /* short circuit */ next++; } if (next != r + 1) { /* * Some entries were merged into r and next * points to the first valid entry that couldn't * be merged. */ MPASS(next->size > 0); /* must be valid */ memcpy(r + 1, next, remaining * sizeof(*r)); #ifdef INVARIANTS /* * This so that the foo->size assertion in the * next iteration of the loop do the right * thing for entries that were pulled up and are * no longer valid. */ MPASS(n < nitems(mem_ranges)); bzero(&mem_ranges[n], (nitems(mem_ranges) - n) * sizeof(struct t4_range)); #endif } } done: /* Done merging the ranges. */ MPASS(n > 0); r = &mem_ranges[0]; for (i = 0; i < n; i++, r++) { if (addr >= r->start && addr + len <= r->start + r->size) return (0); } } return (EFAULT); } static int fwmtype_to_hwmtype(int mtype) { switch (mtype) { case FW_MEMTYPE_EDC0: return (MEM_EDC0); case FW_MEMTYPE_EDC1: return (MEM_EDC1); case FW_MEMTYPE_EXTMEM: return (MEM_MC0); case FW_MEMTYPE_EXTMEM1: return (MEM_MC1); default: panic("%s: cannot translate fw mtype %d.", __func__, mtype); } } /* * Verify that the memory range specified by the memtype/offset/len pair is * valid and lies entirely within the memtype specified. The global address of * the start of the range is returned in addr. */ static int validate_mt_off_len(struct adapter *sc, int mtype, uint32_t off, int len, uint32_t *addr) { uint32_t em, addr_len, maddr; /* Memory can only be accessed in naturally aligned 4 byte units */ if (off & 3 || len & 3 || len == 0) return (EINVAL); em = t4_read_reg(sc, A_MA_TARGET_MEM_ENABLE); switch (fwmtype_to_hwmtype(mtype)) { case MEM_EDC0: if (!(em & F_EDRAM0_ENABLE)) return (EINVAL); addr_len = t4_read_reg(sc, A_MA_EDRAM0_BAR); maddr = G_EDRAM0_BASE(addr_len) << 20; break; case MEM_EDC1: if (!(em & F_EDRAM1_ENABLE)) return (EINVAL); addr_len = t4_read_reg(sc, A_MA_EDRAM1_BAR); maddr = G_EDRAM1_BASE(addr_len) << 20; break; case MEM_MC: if (!(em & F_EXT_MEM_ENABLE)) return (EINVAL); addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY_BAR); maddr = G_EXT_MEM_BASE(addr_len) << 20; break; case MEM_MC1: if (!is_t5(sc) || !(em & F_EXT_MEM1_ENABLE)) return (EINVAL); addr_len = t4_read_reg(sc, A_MA_EXT_MEMORY1_BAR); maddr = G_EXT_MEM1_BASE(addr_len) << 20; break; default: return (EINVAL); } *addr = maddr + off; /* global address */ return (validate_mem_range(sc, *addr, len)); } static int fixup_devlog_params(struct adapter *sc) { struct devlog_params *dparams = &sc->params.devlog; int rc; rc = validate_mt_off_len(sc, dparams->memtype, dparams->start, dparams->size, &dparams->addr); return (rc); } static int cfg_itype_and_nqueues(struct adapter *sc, int n10g, int n1g, int num_vis, struct intrs_and_queues *iaq) { int rc, itype, navail, nrxq10g, nrxq1g, n; int nofldrxq10g = 0, nofldrxq1g = 0; bzero(iaq, sizeof(*iaq)); iaq->ntxq10g = t4_ntxq10g; iaq->ntxq1g = t4_ntxq1g; iaq->ntxq_vi = t4_ntxq_vi; iaq->nrxq10g = nrxq10g = t4_nrxq10g; iaq->nrxq1g = nrxq1g = t4_nrxq1g; iaq->nrxq_vi = t4_nrxq_vi; iaq->rsrv_noflowq = t4_rsrv_noflowq; #ifdef TCP_OFFLOAD if (is_offload(sc)) { iaq->nofldtxq10g = t4_nofldtxq10g; iaq->nofldtxq1g = t4_nofldtxq1g; iaq->nofldtxq_vi = t4_nofldtxq_vi; iaq->nofldrxq10g = nofldrxq10g = t4_nofldrxq10g; iaq->nofldrxq1g = nofldrxq1g = t4_nofldrxq1g; iaq->nofldrxq_vi = t4_nofldrxq_vi; } #endif #ifdef DEV_NETMAP iaq->nnmtxq_vi = t4_nnmtxq_vi; iaq->nnmrxq_vi = t4_nnmrxq_vi; #endif for (itype = INTR_MSIX; itype; itype >>= 1) { if ((itype & t4_intr_types) == 0) continue; /* not allowed */ if (itype == INTR_MSIX) navail = pci_msix_count(sc->dev); else if (itype == INTR_MSI) navail = pci_msi_count(sc->dev); else navail = 1; restart: if (navail == 0) continue; iaq->intr_type = itype; iaq->intr_flags_10g = 0; iaq->intr_flags_1g = 0; /* * Best option: an interrupt vector for errors, one for the * firmware event queue, and one for every rxq (NIC and TOE) of * every VI. The VIs that support netmap use the same * interrupts for the NIC rx queues and the netmap rx queues * because only one set of queues is active at a time. */ iaq->nirq = T4_EXTRA_INTR; iaq->nirq += n10g * (nrxq10g + nofldrxq10g); iaq->nirq += n1g * (nrxq1g + nofldrxq1g); iaq->nirq += (n10g + n1g) * (num_vis - 1) * max(iaq->nrxq_vi, iaq->nnmrxq_vi); /* See comment above. */ iaq->nirq += (n10g + n1g) * (num_vis - 1) * iaq->nofldrxq_vi; if (iaq->nirq <= navail && (itype != INTR_MSI || powerof2(iaq->nirq))) { iaq->intr_flags_10g = INTR_ALL; iaq->intr_flags_1g = INTR_ALL; goto allocate; } /* Disable the VIs (and netmap) if there aren't enough intrs */ if (num_vis > 1) { device_printf(sc->dev, "virtual interfaces disabled " "because num_vis=%u with current settings " "(nrxq10g=%u, nrxq1g=%u, nofldrxq10g=%u, " "nofldrxq1g=%u, nrxq_vi=%u nofldrxq_vi=%u, " "nnmrxq_vi=%u) would need %u interrupts but " "only %u are available.\n", num_vis, nrxq10g, nrxq1g, nofldrxq10g, nofldrxq1g, iaq->nrxq_vi, iaq->nofldrxq_vi, iaq->nnmrxq_vi, iaq->nirq, navail); num_vis = 1; iaq->ntxq_vi = iaq->nrxq_vi = 0; iaq->nofldtxq_vi = iaq->nofldrxq_vi = 0; iaq->nnmtxq_vi = iaq->nnmrxq_vi = 0; goto restart; } /* * Second best option: a vector for errors, one for the firmware * event queue, and vectors for either all the NIC rx queues or * all the TOE rx queues. The queues that don't get vectors * will forward their interrupts to those that do. */ iaq->nirq = T4_EXTRA_INTR; if (nrxq10g >= nofldrxq10g) { iaq->intr_flags_10g = INTR_RXQ; iaq->nirq += n10g * nrxq10g; } else { iaq->intr_flags_10g = INTR_OFLD_RXQ; iaq->nirq += n10g * nofldrxq10g; } if (nrxq1g >= nofldrxq1g) { iaq->intr_flags_1g = INTR_RXQ; iaq->nirq += n1g * nrxq1g; } else { iaq->intr_flags_1g = INTR_OFLD_RXQ; iaq->nirq += n1g * nofldrxq1g; } if (iaq->nirq <= navail && (itype != INTR_MSI || powerof2(iaq->nirq))) goto allocate; /* * Next best option: an interrupt vector for errors, one for the * firmware event queue, and at least one per main-VI. At this * point we know we'll have to downsize nrxq and/or nofldrxq to * fit what's available to us. */ iaq->nirq = T4_EXTRA_INTR; iaq->nirq += n10g + n1g; if (iaq->nirq <= navail) { int leftover = navail - iaq->nirq; if (n10g > 0) { int target = max(nrxq10g, nofldrxq10g); iaq->intr_flags_10g = nrxq10g >= nofldrxq10g ? INTR_RXQ : INTR_OFLD_RXQ; n = 1; while (n < target && leftover >= n10g) { leftover -= n10g; iaq->nirq += n10g; n++; } iaq->nrxq10g = min(n, nrxq10g); #ifdef TCP_OFFLOAD iaq->nofldrxq10g = min(n, nofldrxq10g); #endif } if (n1g > 0) { int target = max(nrxq1g, nofldrxq1g); iaq->intr_flags_1g = nrxq1g >= nofldrxq1g ? INTR_RXQ : INTR_OFLD_RXQ; n = 1; while (n < target && leftover >= n1g) { leftover -= n1g; iaq->nirq += n1g; n++; } iaq->nrxq1g = min(n, nrxq1g); #ifdef TCP_OFFLOAD iaq->nofldrxq1g = min(n, nofldrxq1g); #endif } if (itype != INTR_MSI || powerof2(iaq->nirq)) goto allocate; } /* * Least desirable option: one interrupt vector for everything. */ iaq->nirq = iaq->nrxq10g = iaq->nrxq1g = 1; iaq->intr_flags_10g = iaq->intr_flags_1g = 0; #ifdef TCP_OFFLOAD if (is_offload(sc)) iaq->nofldrxq10g = iaq->nofldrxq1g = 1; #endif allocate: navail = iaq->nirq; rc = 0; if (itype == INTR_MSIX) rc = pci_alloc_msix(sc->dev, &navail); else if (itype == INTR_MSI) rc = pci_alloc_msi(sc->dev, &navail); if (rc == 0) { if (navail == iaq->nirq) return (0); /* * Didn't get the number requested. Use whatever number * the kernel is willing to allocate (it's in navail). */ device_printf(sc->dev, "fewer vectors than requested, " "type=%d, req=%d, rcvd=%d; will downshift req.\n", itype, iaq->nirq, navail); pci_release_msi(sc->dev); goto restart; } device_printf(sc->dev, "failed to allocate vectors:%d, type=%d, req=%d, rcvd=%d\n", itype, rc, iaq->nirq, navail); } device_printf(sc->dev, "failed to find a usable interrupt type. " "allowed=%d, msi-x=%d, msi=%d, intx=1", t4_intr_types, pci_msix_count(sc->dev), pci_msi_count(sc->dev)); return (ENXIO); } #define FW_VERSION(chip) ( \ V_FW_HDR_FW_VER_MAJOR(chip##FW_VERSION_MAJOR) | \ V_FW_HDR_FW_VER_MINOR(chip##FW_VERSION_MINOR) | \ V_FW_HDR_FW_VER_MICRO(chip##FW_VERSION_MICRO) | \ V_FW_HDR_FW_VER_BUILD(chip##FW_VERSION_BUILD)) #define FW_INTFVER(chip, intf) (chip##FW_HDR_INTFVER_##intf) struct fw_info { uint8_t chip; char *kld_name; char *fw_mod_name; struct fw_hdr fw_hdr; /* XXX: waste of space, need a sparse struct */ } fw_info[] = { { .chip = CHELSIO_T4, .kld_name = "t4fw_cfg", .fw_mod_name = "t4fw", .fw_hdr = { .chip = FW_HDR_CHIP_T4, .fw_ver = htobe32_const(FW_VERSION(T4)), .intfver_nic = FW_INTFVER(T4, NIC), .intfver_vnic = FW_INTFVER(T4, VNIC), .intfver_ofld = FW_INTFVER(T4, OFLD), .intfver_ri = FW_INTFVER(T4, RI), .intfver_iscsipdu = FW_INTFVER(T4, ISCSIPDU), .intfver_iscsi = FW_INTFVER(T4, ISCSI), .intfver_fcoepdu = FW_INTFVER(T4, FCOEPDU), .intfver_fcoe = FW_INTFVER(T4, FCOE), }, }, { .chip = CHELSIO_T5, .kld_name = "t5fw_cfg", .fw_mod_name = "t5fw", .fw_hdr = { .chip = FW_HDR_CHIP_T5, .fw_ver = htobe32_const(FW_VERSION(T5)), .intfver_nic = FW_INTFVER(T5, NIC), .intfver_vnic = FW_INTFVER(T5, VNIC), .intfver_ofld = FW_INTFVER(T5, OFLD), .intfver_ri = FW_INTFVER(T5, RI), .intfver_iscsipdu = FW_INTFVER(T5, ISCSIPDU), .intfver_iscsi = FW_INTFVER(T5, ISCSI), .intfver_fcoepdu = FW_INTFVER(T5, FCOEPDU), .intfver_fcoe = FW_INTFVER(T5, FCOE), }, }, { .chip = CHELSIO_T6, .kld_name = "t6fw_cfg", .fw_mod_name = "t6fw", .fw_hdr = { .chip = FW_HDR_CHIP_T6, .fw_ver = htobe32_const(FW_VERSION(T6)), .intfver_nic = FW_INTFVER(T6, NIC), .intfver_vnic = FW_INTFVER(T6, VNIC), .intfver_ofld = FW_INTFVER(T6, OFLD), .intfver_ri = FW_INTFVER(T6, RI), .intfver_iscsipdu = FW_INTFVER(T6, ISCSIPDU), .intfver_iscsi = FW_INTFVER(T6, ISCSI), .intfver_fcoepdu = FW_INTFVER(T6, FCOEPDU), .intfver_fcoe = FW_INTFVER(T6, FCOE), }, } }; static struct fw_info * find_fw_info(int chip) { int i; for (i = 0; i < nitems(fw_info); i++) { if (fw_info[i].chip == chip) return (&fw_info[i]); } return (NULL); } /* * Is the given firmware API compatible with the one the driver was compiled * with? */ static int fw_compatible(const struct fw_hdr *hdr1, const struct fw_hdr *hdr2) { /* short circuit if it's the exact same firmware version */ if (hdr1->chip == hdr2->chip && hdr1->fw_ver == hdr2->fw_ver) return (1); /* * XXX: Is this too conservative? Perhaps I should limit this to the * features that are supported in the driver. */ #define SAME_INTF(x) (hdr1->intfver_##x == hdr2->intfver_##x) if (hdr1->chip == hdr2->chip && SAME_INTF(nic) && SAME_INTF(vnic) && SAME_INTF(ofld) && SAME_INTF(ri) && SAME_INTF(iscsipdu) && SAME_INTF(iscsi) && SAME_INTF(fcoepdu) && SAME_INTF(fcoe)) return (1); #undef SAME_INTF return (0); } /* * The firmware in the KLD is usable, but should it be installed? This routine * explains itself in detail if it indicates the KLD firmware should be * installed. */ static int should_install_kld_fw(struct adapter *sc, int card_fw_usable, int k, int c) { const char *reason; if (!card_fw_usable) { reason = "incompatible or unusable"; goto install; } if (k > c) { reason = "older than the version bundled with this driver"; goto install; } if (t4_fw_install == 2 && k != c) { reason = "different than the version bundled with this driver"; goto install; } return (0); install: if (t4_fw_install == 0) { device_printf(sc->dev, "firmware on card (%u.%u.%u.%u) is %s, " "but the driver is prohibited from installing a different " "firmware on the card.\n", G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c), G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c), reason); return (0); } device_printf(sc->dev, "firmware on card (%u.%u.%u.%u) is %s, " "installing firmware %u.%u.%u.%u on card.\n", G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c), G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c), reason, G_FW_HDR_FW_VER_MAJOR(k), G_FW_HDR_FW_VER_MINOR(k), G_FW_HDR_FW_VER_MICRO(k), G_FW_HDR_FW_VER_BUILD(k)); return (1); } /* * Establish contact with the firmware and determine if we are the master driver * or not, and whether we are responsible for chip initialization. */ static int prep_firmware(struct adapter *sc) { const struct firmware *fw = NULL, *default_cfg; int rc, pf, card_fw_usable, kld_fw_usable, need_fw_reset = 1; enum dev_state state; struct fw_info *fw_info; struct fw_hdr *card_fw; /* fw on the card */ const struct fw_hdr *kld_fw; /* fw in the KLD */ const struct fw_hdr *drv_fw; /* fw header the driver was compiled against */ /* This is the firmware whose headers the driver was compiled against */ fw_info = find_fw_info(chip_id(sc)); if (fw_info == NULL) { device_printf(sc->dev, "unable to look up firmware information for chip %d.\n", chip_id(sc)); return (EINVAL); } drv_fw = &fw_info->fw_hdr; /* * The firmware KLD contains many modules. The KLD name is also the * name of the module that contains the default config file. */ default_cfg = firmware_get(fw_info->kld_name); /* This is the firmware in the KLD */ fw = firmware_get(fw_info->fw_mod_name); if (fw != NULL) { kld_fw = (const void *)fw->data; kld_fw_usable = fw_compatible(drv_fw, kld_fw); } else { kld_fw = NULL; kld_fw_usable = 0; } /* Read the header of the firmware on the card */ card_fw = malloc(sizeof(*card_fw), M_CXGBE, M_ZERO | M_WAITOK); rc = -t4_read_flash(sc, FLASH_FW_START, sizeof (*card_fw) / sizeof (uint32_t), (uint32_t *)card_fw, 1); if (rc == 0) { card_fw_usable = fw_compatible(drv_fw, (const void*)card_fw); if (card_fw->fw_ver == be32toh(0xffffffff)) { uint32_t d = be32toh(kld_fw->fw_ver); if (!kld_fw_usable) { device_printf(sc->dev, "no firmware on the card and no usable " "firmware bundled with the driver.\n"); rc = EIO; goto done; } else if (t4_fw_install == 0) { device_printf(sc->dev, "no firmware on the card and the driver " "is prohibited from installing new " "firmware.\n"); rc = EIO; goto done; } device_printf(sc->dev, "no firmware on the card, " "installing firmware %d.%d.%d.%d\n", G_FW_HDR_FW_VER_MAJOR(d), G_FW_HDR_FW_VER_MINOR(d), G_FW_HDR_FW_VER_MICRO(d), G_FW_HDR_FW_VER_BUILD(d)); rc = t4_fw_forceinstall(sc, fw->data, fw->datasize); if (rc < 0) { rc = -rc; device_printf(sc->dev, "firmware install failed: %d.\n", rc); goto done; } memcpy(card_fw, kld_fw, sizeof(*card_fw)); card_fw_usable = 1; need_fw_reset = 0; } } else { device_printf(sc->dev, "Unable to read card's firmware header: %d\n", rc); card_fw_usable = 0; } /* Contact firmware. */ rc = t4_fw_hello(sc, sc->mbox, sc->mbox, MASTER_MAY, &state); if (rc < 0 || state == DEV_STATE_ERR) { rc = -rc; device_printf(sc->dev, "failed to connect to the firmware: %d, %d.\n", rc, state); goto done; } pf = rc; if (pf == sc->mbox) sc->flags |= MASTER_PF; else if (state == DEV_STATE_UNINIT) { /* * We didn't get to be the master so we definitely won't be * configuring the chip. It's a bug if someone else hasn't * configured it already. */ device_printf(sc->dev, "couldn't be master(%d), " "device not already initialized either(%d).\n", rc, state); rc = EPROTO; goto done; } if (card_fw_usable && card_fw->fw_ver == drv_fw->fw_ver && (!kld_fw_usable || kld_fw->fw_ver == drv_fw->fw_ver)) { /* * Common case: the firmware on the card is an exact match and * the KLD is an exact match too, or the KLD is * absent/incompatible. Note that t4_fw_install = 2 is ignored * here -- use cxgbetool loadfw if you want to reinstall the * same firmware as the one on the card. */ } else if (kld_fw_usable && state == DEV_STATE_UNINIT && should_install_kld_fw(sc, card_fw_usable, be32toh(kld_fw->fw_ver), be32toh(card_fw->fw_ver))) { rc = -t4_fw_upgrade(sc, sc->mbox, fw->data, fw->datasize, 0); if (rc != 0) { device_printf(sc->dev, "failed to install firmware: %d\n", rc); goto done; } /* Installed successfully, update the cached header too. */ memcpy(card_fw, kld_fw, sizeof(*card_fw)); card_fw_usable = 1; need_fw_reset = 0; /* already reset as part of load_fw */ } if (!card_fw_usable) { uint32_t d, c, k; d = ntohl(drv_fw->fw_ver); c = ntohl(card_fw->fw_ver); k = kld_fw ? ntohl(kld_fw->fw_ver) : 0; device_printf(sc->dev, "Cannot find a usable firmware: " "fw_install %d, chip state %d, " "driver compiled with %d.%d.%d.%d, " "card has %d.%d.%d.%d, KLD has %d.%d.%d.%d\n", t4_fw_install, state, G_FW_HDR_FW_VER_MAJOR(d), G_FW_HDR_FW_VER_MINOR(d), G_FW_HDR_FW_VER_MICRO(d), G_FW_HDR_FW_VER_BUILD(d), G_FW_HDR_FW_VER_MAJOR(c), G_FW_HDR_FW_VER_MINOR(c), G_FW_HDR_FW_VER_MICRO(c), G_FW_HDR_FW_VER_BUILD(c), G_FW_HDR_FW_VER_MAJOR(k), G_FW_HDR_FW_VER_MINOR(k), G_FW_HDR_FW_VER_MICRO(k), G_FW_HDR_FW_VER_BUILD(k)); rc = EINVAL; goto done; } /* Reset device */ if (need_fw_reset && (rc = -t4_fw_reset(sc, sc->mbox, F_PIORSTMODE | F_PIORST)) != 0) { device_printf(sc->dev, "firmware reset failed: %d.\n", rc); if (rc != ETIMEDOUT && rc != EIO) t4_fw_bye(sc, sc->mbox); goto done; } sc->flags |= FW_OK; rc = get_params__pre_init(sc); if (rc != 0) goto done; /* error message displayed already */ /* Partition adapter resources as specified in the config file. */ if (state == DEV_STATE_UNINIT) { KASSERT(sc->flags & MASTER_PF, ("%s: trying to change chip settings when not master.", __func__)); rc = partition_resources(sc, default_cfg, fw_info->kld_name); if (rc != 0) goto done; /* error message displayed already */ t4_tweak_chip_settings(sc); /* get basic stuff going */ rc = -t4_fw_initialize(sc, sc->mbox); if (rc != 0) { device_printf(sc->dev, "fw init failed: %d.\n", rc); goto done; } } else { snprintf(sc->cfg_file, sizeof(sc->cfg_file), "pf%d", pf); sc->cfcsum = 0; } done: free(card_fw, M_CXGBE); if (fw != NULL) firmware_put(fw, FIRMWARE_UNLOAD); if (default_cfg != NULL) firmware_put(default_cfg, FIRMWARE_UNLOAD); return (rc); } #define FW_PARAM_DEV(param) \ (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | \ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_##param)) #define FW_PARAM_PFVF(param) \ (V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_PFVF) | \ V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_PFVF_##param)) /* * Partition chip resources for use between various PFs, VFs, etc. */ static int partition_resources(struct adapter *sc, const struct firmware *default_cfg, const char *name_prefix) { const struct firmware *cfg = NULL; int rc = 0; struct fw_caps_config_cmd caps; uint32_t mtype, moff, finicsum, cfcsum; /* * Figure out what configuration file to use. Pick the default config * file for the card if the user hasn't specified one explicitly. */ snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", t4_cfg_file); if (strncmp(t4_cfg_file, DEFAULT_CF, sizeof(t4_cfg_file)) == 0) { /* Card specific overrides go here. */ if (pci_get_device(sc->dev) == 0x440a) snprintf(sc->cfg_file, sizeof(sc->cfg_file), UWIRE_CF); if (is_fpga(sc)) snprintf(sc->cfg_file, sizeof(sc->cfg_file), FPGA_CF); } /* * We need to load another module if the profile is anything except * "default" or "flash". */ if (strncmp(sc->cfg_file, DEFAULT_CF, sizeof(sc->cfg_file)) != 0 && strncmp(sc->cfg_file, FLASH_CF, sizeof(sc->cfg_file)) != 0) { char s[32]; snprintf(s, sizeof(s), "%s_%s", name_prefix, sc->cfg_file); cfg = firmware_get(s); if (cfg == NULL) { if (default_cfg != NULL) { device_printf(sc->dev, "unable to load module \"%s\" for " "configuration profile \"%s\", will use " "the default config file instead.\n", s, sc->cfg_file); snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", DEFAULT_CF); } else { device_printf(sc->dev, "unable to load module \"%s\" for " "configuration profile \"%s\", will use " "the config file on the card's flash " "instead.\n", s, sc->cfg_file); snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", FLASH_CF); } } } if (strncmp(sc->cfg_file, DEFAULT_CF, sizeof(sc->cfg_file)) == 0 && default_cfg == NULL) { device_printf(sc->dev, "default config file not available, will use the config " "file on the card's flash instead.\n"); snprintf(sc->cfg_file, sizeof(sc->cfg_file), "%s", FLASH_CF); } if (strncmp(sc->cfg_file, FLASH_CF, sizeof(sc->cfg_file)) != 0) { u_int cflen; const uint32_t *cfdata; uint32_t param, val, addr; KASSERT(cfg != NULL || default_cfg != NULL, ("%s: no config to upload", __func__)); /* * Ask the firmware where it wants us to upload the config file. */ param = FW_PARAM_DEV(CF); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); if (rc != 0) { /* No support for config file? Shouldn't happen. */ device_printf(sc->dev, "failed to query config file location: %d.\n", rc); goto done; } mtype = G_FW_PARAMS_PARAM_Y(val); moff = G_FW_PARAMS_PARAM_Z(val) << 16; /* * XXX: sheer laziness. We deliberately added 4 bytes of * useless stuffing/comments at the end of the config file so * it's ok to simply throw away the last remaining bytes when * the config file is not an exact multiple of 4. This also * helps with the validate_mt_off_len check. */ if (cfg != NULL) { cflen = cfg->datasize & ~3; cfdata = cfg->data; } else { cflen = default_cfg->datasize & ~3; cfdata = default_cfg->data; } if (cflen > FLASH_CFG_MAX_SIZE) { device_printf(sc->dev, "config file too long (%d, max allowed is %d). " "Will try to use the config on the card, if any.\n", cflen, FLASH_CFG_MAX_SIZE); goto use_config_on_flash; } rc = validate_mt_off_len(sc, mtype, moff, cflen, &addr); if (rc != 0) { device_printf(sc->dev, "%s: addr (%d/0x%x) or len %d is not valid: %d. " "Will try to use the config on the card, if any.\n", __func__, mtype, moff, cflen, rc); goto use_config_on_flash; } write_via_memwin(sc, 2, addr, cfdata, cflen); } else { use_config_on_flash: mtype = FW_MEMTYPE_FLASH; moff = t4_flash_cfg_addr(sc); } bzero(&caps, sizeof(caps)); caps.op_to_write = htobe32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ); caps.cfvalid_to_len16 = htobe32(F_FW_CAPS_CONFIG_CMD_CFVALID | V_FW_CAPS_CONFIG_CMD_MEMTYPE_CF(mtype) | V_FW_CAPS_CONFIG_CMD_MEMADDR64K_CF(moff >> 16) | FW_LEN16(caps)); rc = -t4_wr_mbox(sc, sc->mbox, &caps, sizeof(caps), &caps); if (rc != 0) { device_printf(sc->dev, "failed to pre-process config file: %d " "(mtype %d, moff 0x%x).\n", rc, mtype, moff); goto done; } finicsum = be32toh(caps.finicsum); cfcsum = be32toh(caps.cfcsum); if (finicsum != cfcsum) { device_printf(sc->dev, "WARNING: config file checksum mismatch: %08x %08x\n", finicsum, cfcsum); } sc->cfcsum = cfcsum; #define LIMIT_CAPS(x) do { \ caps.x &= htobe16(t4_##x##_allowed); \ } while (0) /* * Let the firmware know what features will (not) be used so it can tune * things accordingly. */ LIMIT_CAPS(nbmcaps); LIMIT_CAPS(linkcaps); LIMIT_CAPS(switchcaps); LIMIT_CAPS(niccaps); LIMIT_CAPS(toecaps); LIMIT_CAPS(rdmacaps); LIMIT_CAPS(cryptocaps); LIMIT_CAPS(iscsicaps); LIMIT_CAPS(fcoecaps); #undef LIMIT_CAPS caps.op_to_write = htobe32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_WRITE); caps.cfvalid_to_len16 = htobe32(FW_LEN16(caps)); rc = -t4_wr_mbox(sc, sc->mbox, &caps, sizeof(caps), NULL); if (rc != 0) { device_printf(sc->dev, "failed to process config file: %d.\n", rc); } done: if (cfg != NULL) firmware_put(cfg, FIRMWARE_UNLOAD); return (rc); } /* * Retrieve parameters that are needed (or nice to have) very early. */ static int get_params__pre_init(struct adapter *sc) { int rc; uint32_t param[2], val[2]; t4_get_version_info(sc); snprintf(sc->fw_version, sizeof(sc->fw_version), "%u.%u.%u.%u", G_FW_HDR_FW_VER_MAJOR(sc->params.fw_vers), G_FW_HDR_FW_VER_MINOR(sc->params.fw_vers), G_FW_HDR_FW_VER_MICRO(sc->params.fw_vers), G_FW_HDR_FW_VER_BUILD(sc->params.fw_vers)); snprintf(sc->bs_version, sizeof(sc->bs_version), "%u.%u.%u.%u", G_FW_HDR_FW_VER_MAJOR(sc->params.bs_vers), G_FW_HDR_FW_VER_MINOR(sc->params.bs_vers), G_FW_HDR_FW_VER_MICRO(sc->params.bs_vers), G_FW_HDR_FW_VER_BUILD(sc->params.bs_vers)); snprintf(sc->tp_version, sizeof(sc->tp_version), "%u.%u.%u.%u", G_FW_HDR_FW_VER_MAJOR(sc->params.tp_vers), G_FW_HDR_FW_VER_MINOR(sc->params.tp_vers), G_FW_HDR_FW_VER_MICRO(sc->params.tp_vers), G_FW_HDR_FW_VER_BUILD(sc->params.tp_vers)); snprintf(sc->er_version, sizeof(sc->er_version), "%u.%u.%u.%u", G_FW_HDR_FW_VER_MAJOR(sc->params.er_vers), G_FW_HDR_FW_VER_MINOR(sc->params.er_vers), G_FW_HDR_FW_VER_MICRO(sc->params.er_vers), G_FW_HDR_FW_VER_BUILD(sc->params.er_vers)); param[0] = FW_PARAM_DEV(PORTVEC); param[1] = FW_PARAM_DEV(CCLK); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 2, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query parameters (pre_init): %d.\n", rc); return (rc); } sc->params.portvec = val[0]; sc->params.nports = bitcount32(val[0]); sc->params.vpd.cclk = val[1]; /* Read device log parameters. */ rc = -t4_init_devlog_params(sc, 1); if (rc == 0) fixup_devlog_params(sc); else { device_printf(sc->dev, "failed to get devlog parameters: %d.\n", rc); rc = 0; /* devlog isn't critical for device operation */ } return (rc); } /* * Retrieve various parameters that are of interest to the driver. The device * has been initialized by the firmware at this point. */ static int get_params__post_init(struct adapter *sc) { int rc; uint32_t param[7], val[7]; struct fw_caps_config_cmd caps; param[0] = FW_PARAM_PFVF(IQFLINT_START); param[1] = FW_PARAM_PFVF(EQ_START); param[2] = FW_PARAM_PFVF(FILTER_START); param[3] = FW_PARAM_PFVF(FILTER_END); param[4] = FW_PARAM_PFVF(L2T_START); param[5] = FW_PARAM_PFVF(L2T_END); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query parameters (post_init): %d.\n", rc); return (rc); } sc->sge.iq_start = val[0]; sc->sge.eq_start = val[1]; sc->tids.ftid_base = val[2]; sc->tids.nftids = val[3] - val[2] + 1; sc->params.ftid_min = val[2]; sc->params.ftid_max = val[3]; sc->vres.l2t.start = val[4]; sc->vres.l2t.size = val[5] - val[4] + 1; KASSERT(sc->vres.l2t.size <= L2T_SIZE, ("%s: L2 table size (%u) larger than expected (%u)", __func__, sc->vres.l2t.size, L2T_SIZE)); /* get capabilites */ bzero(&caps, sizeof(caps)); caps.op_to_write = htobe32(V_FW_CMD_OP(FW_CAPS_CONFIG_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ); caps.cfvalid_to_len16 = htobe32(FW_LEN16(caps)); rc = -t4_wr_mbox(sc, sc->mbox, &caps, sizeof(caps), &caps); if (rc != 0) { device_printf(sc->dev, "failed to get card capabilities: %d.\n", rc); return (rc); } #define READ_CAPS(x) do { \ sc->x = htobe16(caps.x); \ } while (0) READ_CAPS(nbmcaps); READ_CAPS(linkcaps); READ_CAPS(switchcaps); READ_CAPS(niccaps); READ_CAPS(toecaps); READ_CAPS(rdmacaps); READ_CAPS(cryptocaps); READ_CAPS(iscsicaps); READ_CAPS(fcoecaps); if (sc->niccaps & FW_CAPS_CONFIG_NIC_ETHOFLD) { param[0] = FW_PARAM_PFVF(ETHOFLD_START); param[1] = FW_PARAM_PFVF(ETHOFLD_END); param[2] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 3, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query NIC parameters: %d.\n", rc); return (rc); } sc->tids.etid_base = val[0]; sc->params.etid_min = val[0]; sc->tids.netids = val[1] - val[0] + 1; sc->params.netids = sc->tids.netids; sc->params.eo_wr_cred = val[2]; sc->params.ethoffload = 1; } if (sc->toecaps) { /* query offload-related parameters */ param[0] = FW_PARAM_DEV(NTID); param[1] = FW_PARAM_PFVF(SERVER_START); param[2] = FW_PARAM_PFVF(SERVER_END); param[3] = FW_PARAM_PFVF(TDDP_START); param[4] = FW_PARAM_PFVF(TDDP_END); param[5] = FW_PARAM_DEV(FLOWC_BUFFIFO_SZ); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query TOE parameters: %d.\n", rc); return (rc); } sc->tids.ntids = val[0]; sc->tids.natids = min(sc->tids.ntids / 2, MAX_ATIDS); sc->tids.stid_base = val[1]; sc->tids.nstids = val[2] - val[1] + 1; sc->vres.ddp.start = val[3]; sc->vres.ddp.size = val[4] - val[3] + 1; sc->params.ofldq_wr_cred = val[5]; sc->params.offload = 1; } if (sc->rdmacaps) { param[0] = FW_PARAM_PFVF(STAG_START); param[1] = FW_PARAM_PFVF(STAG_END); param[2] = FW_PARAM_PFVF(RQ_START); param[3] = FW_PARAM_PFVF(RQ_END); param[4] = FW_PARAM_PFVF(PBL_START); param[5] = FW_PARAM_PFVF(PBL_END); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query RDMA parameters(1): %d.\n", rc); return (rc); } sc->vres.stag.start = val[0]; sc->vres.stag.size = val[1] - val[0] + 1; sc->vres.rq.start = val[2]; sc->vres.rq.size = val[3] - val[2] + 1; sc->vres.pbl.start = val[4]; sc->vres.pbl.size = val[5] - val[4] + 1; param[0] = FW_PARAM_PFVF(SQRQ_START); param[1] = FW_PARAM_PFVF(SQRQ_END); param[2] = FW_PARAM_PFVF(CQ_START); param[3] = FW_PARAM_PFVF(CQ_END); param[4] = FW_PARAM_PFVF(OCQ_START); param[5] = FW_PARAM_PFVF(OCQ_END); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 6, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query RDMA parameters(2): %d.\n", rc); return (rc); } sc->vres.qp.start = val[0]; sc->vres.qp.size = val[1] - val[0] + 1; sc->vres.cq.start = val[2]; sc->vres.cq.size = val[3] - val[2] + 1; sc->vres.ocq.start = val[4]; sc->vres.ocq.size = val[5] - val[4] + 1; param[0] = FW_PARAM_PFVF(SRQ_START); param[1] = FW_PARAM_PFVF(SRQ_END); param[2] = FW_PARAM_DEV(MAXORDIRD_QP); param[3] = FW_PARAM_DEV(MAXIRD_ADAPTER); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 4, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query RDMA parameters(3): %d.\n", rc); return (rc); } sc->vres.srq.start = val[0]; sc->vres.srq.size = val[1] - val[0] + 1; sc->params.max_ordird_qp = val[2]; sc->params.max_ird_adapter = val[3]; } if (sc->iscsicaps) { param[0] = FW_PARAM_PFVF(ISCSI_START); param[1] = FW_PARAM_PFVF(ISCSI_END); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 2, param, val); if (rc != 0) { device_printf(sc->dev, "failed to query iSCSI parameters: %d.\n", rc); return (rc); } sc->vres.iscsi.start = val[0]; sc->vres.iscsi.size = val[1] - val[0] + 1; } t4_init_sge_params(sc); /* * We've got the params we wanted to query via the firmware. Now grab * some others directly from the chip. */ rc = t4_read_chip_settings(sc); return (rc); } static int set_params__post_init(struct adapter *sc) { uint32_t param, val; int i, v, shift; char s[32]; /* ask for encapsulated CPLs */ param = FW_PARAM_PFVF(CPLFW4MSG_ENCAP); val = 1; (void)t4_set_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); /* * Override the TOE timers with user provided tunables. This is not the * recommended way to change the timers (the firmware config file is) so * these tunables are not documented. * * All the timer tunables are in milliseconds. */ if (TUNABLE_INT_FETCH("hw.cxgbe.toe.keepalive_idle", &v)) { t4_set_reg_field(sc, A_TP_KEEP_IDLE, V_KEEPALIVEIDLE(M_KEEPALIVEIDLE), V_KEEPALIVEIDLE(ms_to_tcp_ticks(sc, v))); } if (TUNABLE_INT_FETCH("hw.cxgbe.toe.keepalive_interval", &v)) { t4_set_reg_field(sc, A_TP_KEEP_INTVL, V_KEEPALIVEINTVL(M_KEEPALIVEINTVL), V_KEEPALIVEINTVL(ms_to_tcp_ticks(sc, v))); } if (TUNABLE_INT_FETCH("hw.cxgbe.toe.keepalive_count", &v)) { v &= M_KEEPALIVEMAXR1; t4_set_reg_field(sc, A_TP_SHIFT_CNT, V_KEEPALIVEMAXR1(M_KEEPALIVEMAXR1) | V_KEEPALIVEMAXR2(M_KEEPALIVEMAXR2), V_KEEPALIVEMAXR1(1) | V_KEEPALIVEMAXR2(v)); } if (TUNABLE_INT_FETCH("hw.cxgbe.toe.rexmt_min", &v)) { t4_set_reg_field(sc, A_TP_RXT_MIN, V_RXTMIN(M_RXTMIN), V_RXTMIN(ms_to_tcp_ticks(sc, v))); } if (TUNABLE_INT_FETCH("hw.cxgbe.toe.rexmt_max", &v)) { t4_set_reg_field(sc, A_TP_RXT_MAX, V_RXTMAX(M_RXTMAX), V_RXTMAX(ms_to_tcp_ticks(sc, v))); } if (TUNABLE_INT_FETCH("hw.cxgbe.toe.rexmt_count", &v)) { v &= M_RXTSHIFTMAXR1; t4_set_reg_field(sc, A_TP_SHIFT_CNT, V_RXTSHIFTMAXR1(M_RXTSHIFTMAXR1) | V_RXTSHIFTMAXR2(M_RXTSHIFTMAXR2), V_RXTSHIFTMAXR1(1) | V_RXTSHIFTMAXR2(v)); } for (i = 0; i < 16; i++) { snprintf(s, sizeof(s), "hw.cxgbe.toe.rexmt_backoff.%d", i); if (TUNABLE_INT_FETCH(s, &v)) { v &= M_TIMERBACKOFFINDEX0; shift = (i & 3) << 3; t4_set_reg_field(sc, A_TP_TCP_BACKOFF_REG0 + (i & ~3), M_TIMERBACKOFFINDEX0 << shift, v << shift); } } return (0); } #undef FW_PARAM_PFVF #undef FW_PARAM_DEV static void t4_set_desc(struct adapter *sc) { char buf[128]; struct adapter_params *p = &sc->params; snprintf(buf, sizeof(buf), "Chelsio %s", p->vpd.id); device_set_desc_copy(sc->dev, buf); } static void build_medialist(struct port_info *pi, struct ifmedia *media) { int m; PORT_LOCK_ASSERT_OWNED(pi); ifmedia_removeall(media); /* * XXX: Would it be better to ifmedia_add all 4 combinations of pause * settings for every speed instead of just txpause|rxpause? ifconfig * media display looks much better if autoselect is the only case where * ifm_current is different from ifm_active. If the user picks anything * except txpause|rxpause the display is ugly. */ m = IFM_ETHER | IFM_FDX | IFM_ETH_TXPAUSE | IFM_ETH_RXPAUSE; switch(pi->port_type) { case FW_PORT_TYPE_BT_XFI: case FW_PORT_TYPE_BT_XAUI: ifmedia_add(media, m | IFM_10G_T, 0, NULL); /* fall through */ case FW_PORT_TYPE_BT_SGMII: ifmedia_add(media, m | IFM_1000_T, 0, NULL); ifmedia_add(media, m | IFM_100_TX, 0, NULL); ifmedia_add(media, IFM_ETHER | IFM_AUTO, 0, NULL); ifmedia_set(media, IFM_ETHER | IFM_AUTO); break; case FW_PORT_TYPE_CX4: ifmedia_add(media, m | IFM_10G_CX4, 0, NULL); ifmedia_set(media, m | IFM_10G_CX4); break; case FW_PORT_TYPE_QSFP_10G: case FW_PORT_TYPE_SFP: case FW_PORT_TYPE_FIBER_XFI: case FW_PORT_TYPE_FIBER_XAUI: switch (pi->mod_type) { case FW_PORT_MOD_TYPE_LR: ifmedia_add(media, m | IFM_10G_LR, 0, NULL); ifmedia_set(media, m | IFM_10G_LR); break; case FW_PORT_MOD_TYPE_SR: ifmedia_add(media, m | IFM_10G_SR, 0, NULL); ifmedia_set(media, m | IFM_10G_SR); break; case FW_PORT_MOD_TYPE_LRM: ifmedia_add(media, m | IFM_10G_LRM, 0, NULL); ifmedia_set(media, m | IFM_10G_LRM); break; case FW_PORT_MOD_TYPE_TWINAX_PASSIVE: case FW_PORT_MOD_TYPE_TWINAX_ACTIVE: ifmedia_add(media, m | IFM_10G_TWINAX, 0, NULL); ifmedia_set(media, m | IFM_10G_TWINAX); break; case FW_PORT_MOD_TYPE_NONE: m &= ~IFM_FDX; ifmedia_add(media, m | IFM_NONE, 0, NULL); ifmedia_set(media, m | IFM_NONE); break; case FW_PORT_MOD_TYPE_NA: case FW_PORT_MOD_TYPE_ER: default: device_printf(pi->dev, "unknown port_type (%d), mod_type (%d)\n", pi->port_type, pi->mod_type); ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL); ifmedia_set(media, m | IFM_UNKNOWN); break; } break; case FW_PORT_TYPE_CR_QSFP: case FW_PORT_TYPE_SFP28: case FW_PORT_TYPE_KR_SFP28: switch (pi->mod_type) { case FW_PORT_MOD_TYPE_SR: ifmedia_add(media, m | IFM_25G_SR, 0, NULL); ifmedia_set(media, m | IFM_25G_SR); break; case FW_PORT_MOD_TYPE_TWINAX_PASSIVE: case FW_PORT_MOD_TYPE_TWINAX_ACTIVE: ifmedia_add(media, m | IFM_25G_CR, 0, NULL); ifmedia_set(media, m | IFM_25G_CR); break; case FW_PORT_MOD_TYPE_NONE: m &= ~IFM_FDX; ifmedia_add(media, m | IFM_NONE, 0, NULL); ifmedia_set(media, m | IFM_NONE); break; default: device_printf(pi->dev, "unknown port_type (%d), mod_type (%d)\n", pi->port_type, pi->mod_type); ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL); ifmedia_set(media, m | IFM_UNKNOWN); break; } break; case FW_PORT_TYPE_QSFP: switch (pi->mod_type) { case FW_PORT_MOD_TYPE_LR: ifmedia_add(media, m | IFM_40G_LR4, 0, NULL); ifmedia_set(media, m | IFM_40G_LR4); break; case FW_PORT_MOD_TYPE_SR: ifmedia_add(media, m | IFM_40G_SR4, 0, NULL); ifmedia_set(media, m | IFM_40G_SR4); break; case FW_PORT_MOD_TYPE_TWINAX_PASSIVE: case FW_PORT_MOD_TYPE_TWINAX_ACTIVE: ifmedia_add(media, m | IFM_40G_CR4, 0, NULL); ifmedia_set(media, m | IFM_40G_CR4); break; case FW_PORT_MOD_TYPE_NONE: m &= ~IFM_FDX; ifmedia_add(media, m | IFM_NONE, 0, NULL); ifmedia_set(media, m | IFM_NONE); break; default: device_printf(pi->dev, "unknown port_type (%d), mod_type (%d)\n", pi->port_type, pi->mod_type); ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL); ifmedia_set(media, m | IFM_UNKNOWN); break; } break; case FW_PORT_TYPE_KR4_100G: case FW_PORT_TYPE_CR4_QSFP: switch (pi->mod_type) { case FW_PORT_MOD_TYPE_LR: ifmedia_add(media, m | IFM_100G_LR4, 0, NULL); ifmedia_set(media, m | IFM_100G_LR4); break; case FW_PORT_MOD_TYPE_SR: ifmedia_add(media, m | IFM_100G_SR4, 0, NULL); ifmedia_set(media, m | IFM_100G_SR4); break; case FW_PORT_MOD_TYPE_TWINAX_PASSIVE: case FW_PORT_MOD_TYPE_TWINAX_ACTIVE: ifmedia_add(media, m | IFM_100G_CR4, 0, NULL); ifmedia_set(media, m | IFM_100G_CR4); break; case FW_PORT_MOD_TYPE_NONE: m &= ~IFM_FDX; ifmedia_add(media, m | IFM_NONE, 0, NULL); ifmedia_set(media, m | IFM_NONE); break; default: device_printf(pi->dev, "unknown port_type (%d), mod_type (%d)\n", pi->port_type, pi->mod_type); ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL); ifmedia_set(media, m | IFM_UNKNOWN); break; } break; default: device_printf(pi->dev, "unknown port_type (%d), mod_type (%d)\n", pi->port_type, pi->mod_type); ifmedia_add(media, m | IFM_UNKNOWN, 0, NULL); ifmedia_set(media, m | IFM_UNKNOWN); break; } } /* * Update all the requested_* fields in the link config and then send a mailbox * command to apply the settings. */ static void init_l1cfg(struct port_info *pi) { struct adapter *sc = pi->adapter; struct link_config *lc = &pi->link_cfg; int rc; ASSERT_SYNCHRONIZED_OP(sc); if (t4_autoneg != 0 && lc->supported & FW_PORT_CAP_ANEG) { lc->requested_aneg = AUTONEG_ENABLE; lc->requested_speed = 0; } else { lc->requested_aneg = AUTONEG_DISABLE; lc->requested_speed = port_top_speed(pi); /* in Gbps */ } lc->requested_fc = t4_pause_settings & (PAUSE_TX | PAUSE_RX); if (t4_fec != -1) { lc->requested_fec = t4_fec & (FEC_RS | FEC_BASER_RS | FEC_RESERVED); } else { /* Use the suggested value provided by the firmware in acaps */ if (lc->advertising & FW_PORT_CAP_FEC_RS) lc->requested_fec = FEC_RS; else if (lc->advertising & FW_PORT_CAP_FEC_BASER_RS) lc->requested_fec = FEC_BASER_RS; else if (lc->advertising & FW_PORT_CAP_FEC_RESERVED) lc->requested_fec = FEC_RESERVED; else lc->requested_fec = 0; } rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc); if (rc != 0) { device_printf(pi->dev, "l1cfg failed: %d\n", rc); } else { lc->fc = lc->requested_fc; lc->fec = lc->requested_fec; } } #define FW_MAC_EXACT_CHUNK 7 /* * Program the port's XGMAC based on parameters in ifnet. The caller also * indicates which parameters should be programmed (the rest are left alone). */ int update_mac_settings(struct ifnet *ifp, int flags) { int rc = 0; struct vi_info *vi = ifp->if_softc; struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; int mtu = -1, promisc = -1, allmulti = -1, vlanex = -1; ASSERT_SYNCHRONIZED_OP(sc); KASSERT(flags, ("%s: not told what to update.", __func__)); if (flags & XGMAC_MTU) mtu = ifp->if_mtu; if (flags & XGMAC_PROMISC) promisc = ifp->if_flags & IFF_PROMISC ? 1 : 0; if (flags & XGMAC_ALLMULTI) allmulti = ifp->if_flags & IFF_ALLMULTI ? 1 : 0; if (flags & XGMAC_VLANEX) vlanex = ifp->if_capenable & IFCAP_VLAN_HWTAGGING ? 1 : 0; if (flags & (XGMAC_MTU|XGMAC_PROMISC|XGMAC_ALLMULTI|XGMAC_VLANEX)) { rc = -t4_set_rxmode(sc, sc->mbox, vi->viid, mtu, promisc, allmulti, 1, vlanex, false); if (rc) { if_printf(ifp, "set_rxmode (%x) failed: %d\n", flags, rc); return (rc); } } if (flags & XGMAC_UCADDR) { uint8_t ucaddr[ETHER_ADDR_LEN]; bcopy(IF_LLADDR(ifp), ucaddr, sizeof(ucaddr)); rc = t4_change_mac(sc, sc->mbox, vi->viid, vi->xact_addr_filt, ucaddr, true, true); if (rc < 0) { rc = -rc; if_printf(ifp, "change_mac failed: %d\n", rc); return (rc); } else { vi->xact_addr_filt = rc; rc = 0; } } if (flags & XGMAC_MCADDRS) { const uint8_t *mcaddr[FW_MAC_EXACT_CHUNK]; int del = 1; uint64_t hash = 0; struct ifmultiaddr *ifma; int i = 0, j; if_maddr_rlock(ifp); TAILQ_FOREACH(ifma, &ifp->if_multiaddrs, ifma_link) { if (ifma->ifma_addr->sa_family != AF_LINK) continue; mcaddr[i] = LLADDR((struct sockaddr_dl *)ifma->ifma_addr); MPASS(ETHER_IS_MULTICAST(mcaddr[i])); i++; if (i == FW_MAC_EXACT_CHUNK) { rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid, del, i, mcaddr, NULL, &hash, 0); if (rc < 0) { rc = -rc; for (j = 0; j < i; j++) { if_printf(ifp, "failed to add mc address" " %02x:%02x:%02x:" "%02x:%02x:%02x rc=%d\n", mcaddr[j][0], mcaddr[j][1], mcaddr[j][2], mcaddr[j][3], mcaddr[j][4], mcaddr[j][5], rc); } goto mcfail; } del = 0; i = 0; } } if (i > 0) { rc = t4_alloc_mac_filt(sc, sc->mbox, vi->viid, del, i, mcaddr, NULL, &hash, 0); if (rc < 0) { rc = -rc; for (j = 0; j < i; j++) { if_printf(ifp, "failed to add mc address" " %02x:%02x:%02x:" "%02x:%02x:%02x rc=%d\n", mcaddr[j][0], mcaddr[j][1], mcaddr[j][2], mcaddr[j][3], mcaddr[j][4], mcaddr[j][5], rc); } goto mcfail; } } rc = -t4_set_addr_hash(sc, sc->mbox, vi->viid, 0, hash, 0); if (rc != 0) if_printf(ifp, "failed to set mc address hash: %d", rc); mcfail: if_maddr_runlock(ifp); } return (rc); } /* * {begin|end}_synchronized_op must be called from the same thread. */ int begin_synchronized_op(struct adapter *sc, struct vi_info *vi, int flags, char *wmesg) { int rc, pri; #ifdef WITNESS /* the caller thinks it's ok to sleep, but is it really? */ if (flags & SLEEP_OK) WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL, "begin_synchronized_op"); #endif if (INTR_OK) pri = PCATCH; else pri = 0; ADAPTER_LOCK(sc); for (;;) { if (vi && IS_DOOMED(vi)) { rc = ENXIO; goto done; } if (!IS_BUSY(sc)) { rc = 0; break; } if (!(flags & SLEEP_OK)) { rc = EBUSY; goto done; } if (mtx_sleep(&sc->flags, &sc->sc_lock, pri, wmesg, 0)) { rc = EINTR; goto done; } } KASSERT(!IS_BUSY(sc), ("%s: controller busy.", __func__)); SET_BUSY(sc); #ifdef INVARIANTS sc->last_op = wmesg; sc->last_op_thr = curthread; sc->last_op_flags = flags; #endif done: if (!(flags & HOLD_LOCK) || rc) ADAPTER_UNLOCK(sc); return (rc); } /* * Tell if_ioctl and if_init that the VI is going away. This is * special variant of begin_synchronized_op and must be paired with a * call to end_synchronized_op. */ void doom_vi(struct adapter *sc, struct vi_info *vi) { ADAPTER_LOCK(sc); SET_DOOMED(vi); wakeup(&sc->flags); while (IS_BUSY(sc)) mtx_sleep(&sc->flags, &sc->sc_lock, 0, "t4detach", 0); SET_BUSY(sc); #ifdef INVARIANTS sc->last_op = "t4detach"; sc->last_op_thr = curthread; sc->last_op_flags = 0; #endif ADAPTER_UNLOCK(sc); } /* * {begin|end}_synchronized_op must be called from the same thread. */ void end_synchronized_op(struct adapter *sc, int flags) { if (flags & LOCK_HELD) ADAPTER_LOCK_ASSERT_OWNED(sc); else ADAPTER_LOCK(sc); KASSERT(IS_BUSY(sc), ("%s: controller not busy.", __func__)); CLR_BUSY(sc); wakeup(&sc->flags); ADAPTER_UNLOCK(sc); } static int cxgbe_init_synchronized(struct vi_info *vi) { struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; struct ifnet *ifp = vi->ifp; int rc = 0, i; struct sge_txq *txq; ASSERT_SYNCHRONIZED_OP(sc); if (ifp->if_drv_flags & IFF_DRV_RUNNING) return (0); /* already running */ if (!(sc->flags & FULL_INIT_DONE) && ((rc = adapter_full_init(sc)) != 0)) return (rc); /* error message displayed already */ if (!(vi->flags & VI_INIT_DONE) && ((rc = vi_full_init(vi)) != 0)) return (rc); /* error message displayed already */ rc = update_mac_settings(ifp, XGMAC_ALL); if (rc) goto done; /* error message displayed already */ rc = -t4_enable_vi(sc, sc->mbox, vi->viid, true, true); if (rc != 0) { if_printf(ifp, "enable_vi failed: %d\n", rc); goto done; } /* * Can't fail from this point onwards. Review cxgbe_uninit_synchronized * if this changes. */ for_each_txq(vi, i, txq) { TXQ_LOCK(txq); txq->eq.flags |= EQ_ENABLED; TXQ_UNLOCK(txq); } /* * The first iq of the first port to come up is used for tracing. */ if (sc->traceq < 0 && IS_MAIN_VI(vi)) { sc->traceq = sc->sge.rxq[vi->first_rxq].iq.abs_id; t4_write_reg(sc, is_t4(sc) ? A_MPS_TRC_RSS_CONTROL : A_MPS_T5_TRC_RSS_CONTROL, V_RSSCONTROL(pi->tx_chan) | V_QUEUENUMBER(sc->traceq)); pi->flags |= HAS_TRACEQ; } /* all ok */ PORT_LOCK(pi); if (pi->up_vis++ == 0) { t4_update_port_info(pi); build_medialist(vi->pi, &vi->media); init_l1cfg(pi); } ifp->if_drv_flags |= IFF_DRV_RUNNING; if (pi->nvi > 1 || sc->flags & IS_VF) callout_reset(&vi->tick, hz, vi_tick, vi); else callout_reset(&pi->tick, hz, cxgbe_tick, pi); PORT_UNLOCK(pi); done: if (rc != 0) cxgbe_uninit_synchronized(vi); return (rc); } /* * Idempotent. */ static int cxgbe_uninit_synchronized(struct vi_info *vi) { struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; struct ifnet *ifp = vi->ifp; int rc, i; struct sge_txq *txq; ASSERT_SYNCHRONIZED_OP(sc); if (!(vi->flags & VI_INIT_DONE)) { KASSERT(!(ifp->if_drv_flags & IFF_DRV_RUNNING), ("uninited VI is running")); return (0); } /* * Disable the VI so that all its data in either direction is discarded * by the MPS. Leave everything else (the queues, interrupts, and 1Hz * tick) intact as the TP can deliver negative advice or data that it's * holding in its RAM (for an offloaded connection) even after the VI is * disabled. */ rc = -t4_enable_vi(sc, sc->mbox, vi->viid, false, false); if (rc) { if_printf(ifp, "disable_vi failed: %d\n", rc); return (rc); } for_each_txq(vi, i, txq) { TXQ_LOCK(txq); txq->eq.flags &= ~EQ_ENABLED; TXQ_UNLOCK(txq); } PORT_LOCK(pi); if (pi->nvi > 1 || sc->flags & IS_VF) callout_stop(&vi->tick); else callout_stop(&pi->tick); if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) { PORT_UNLOCK(pi); return (0); } ifp->if_drv_flags &= ~IFF_DRV_RUNNING; pi->up_vis--; if (pi->up_vis > 0) { PORT_UNLOCK(pi); return (0); } PORT_UNLOCK(pi); pi->link_cfg.link_ok = 0; pi->link_cfg.speed = 0; pi->link_cfg.link_down_rc = 255; t4_os_link_changed(pi, NULL); return (0); } /* * It is ok for this function to fail midway and return right away. t4_detach * will walk the entire sc->irq list and clean up whatever is valid. */ int t4_setup_intr_handlers(struct adapter *sc) { int rc, rid, p, q, v; char s[8]; struct irq *irq; struct port_info *pi; struct vi_info *vi; struct sge *sge = &sc->sge; struct sge_rxq *rxq; #ifdef TCP_OFFLOAD struct sge_ofld_rxq *ofld_rxq; #endif #ifdef DEV_NETMAP struct sge_nm_rxq *nm_rxq; #endif #ifdef RSS int nbuckets = rss_getnumbuckets(); #endif /* * Setup interrupts. */ irq = &sc->irq[0]; rid = sc->intr_type == INTR_INTX ? 0 : 1; if (sc->intr_count == 1) return (t4_alloc_irq(sc, irq, rid, t4_intr_all, sc, "all")); /* Multiple interrupts. */ if (sc->flags & IS_VF) KASSERT(sc->intr_count >= T4VF_EXTRA_INTR + sc->params.nports, ("%s: too few intr.", __func__)); else KASSERT(sc->intr_count >= T4_EXTRA_INTR + sc->params.nports, ("%s: too few intr.", __func__)); /* The first one is always error intr on PFs */ if (!(sc->flags & IS_VF)) { rc = t4_alloc_irq(sc, irq, rid, t4_intr_err, sc, "err"); if (rc != 0) return (rc); irq++; rid++; } /* The second one is always the firmware event queue (first on VFs) */ rc = t4_alloc_irq(sc, irq, rid, t4_intr_evt, &sge->fwq, "evt"); if (rc != 0) return (rc); irq++; rid++; for_each_port(sc, p) { pi = sc->port[p]; for_each_vi(pi, v, vi) { vi->first_intr = rid - 1; if (vi->nnmrxq > 0) { int n = max(vi->nrxq, vi->nnmrxq); MPASS(vi->flags & INTR_RXQ); rxq = &sge->rxq[vi->first_rxq]; #ifdef DEV_NETMAP nm_rxq = &sge->nm_rxq[vi->first_nm_rxq]; #endif for (q = 0; q < n; q++) { snprintf(s, sizeof(s), "%x%c%x", p, 'a' + v, q); if (q < vi->nrxq) irq->rxq = rxq++; #ifdef DEV_NETMAP if (q < vi->nnmrxq) irq->nm_rxq = nm_rxq++; #endif rc = t4_alloc_irq(sc, irq, rid, t4_vi_intr, irq, s); if (rc != 0) return (rc); irq++; rid++; vi->nintr++; } } else if (vi->flags & INTR_RXQ) { for_each_rxq(vi, q, rxq) { snprintf(s, sizeof(s), "%x%c%x", p, 'a' + v, q); rc = t4_alloc_irq(sc, irq, rid, t4_intr, rxq, s); if (rc != 0) return (rc); #ifdef RSS bus_bind_intr(sc->dev, irq->res, rss_getcpu(q % nbuckets)); #endif irq++; rid++; vi->nintr++; } } #ifdef TCP_OFFLOAD if (vi->flags & INTR_OFLD_RXQ) { for_each_ofld_rxq(vi, q, ofld_rxq) { snprintf(s, sizeof(s), "%x%c%x", p, 'A' + v, q); rc = t4_alloc_irq(sc, irq, rid, t4_intr, ofld_rxq, s); if (rc != 0) return (rc); irq++; rid++; vi->nintr++; } } #endif } } MPASS(irq == &sc->irq[sc->intr_count]); return (0); } int adapter_full_init(struct adapter *sc) { int rc, i; #ifdef RSS uint32_t raw_rss_key[RSS_KEYSIZE / sizeof(uint32_t)]; uint32_t rss_key[RSS_KEYSIZE / sizeof(uint32_t)]; #endif ASSERT_SYNCHRONIZED_OP(sc); ADAPTER_LOCK_ASSERT_NOTOWNED(sc); KASSERT((sc->flags & FULL_INIT_DONE) == 0, ("%s: FULL_INIT_DONE already", __func__)); /* * queues that belong to the adapter (not any particular port). */ rc = t4_setup_adapter_queues(sc); if (rc != 0) goto done; for (i = 0; i < nitems(sc->tq); i++) { sc->tq[i] = taskqueue_create("t4 taskq", M_NOWAIT, taskqueue_thread_enqueue, &sc->tq[i]); if (sc->tq[i] == NULL) { device_printf(sc->dev, "failed to allocate task queue %d\n", i); rc = ENOMEM; goto done; } taskqueue_start_threads(&sc->tq[i], 1, PI_NET, "%s tq%d", device_get_nameunit(sc->dev), i); } #ifdef RSS MPASS(RSS_KEYSIZE == 40); rss_getkey((void *)&raw_rss_key[0]); for (i = 0; i < nitems(rss_key); i++) { rss_key[i] = htobe32(raw_rss_key[nitems(rss_key) - 1 - i]); } t4_write_rss_key(sc, &rss_key[0], -1, 1); #endif if (!(sc->flags & IS_VF)) t4_intr_enable(sc); sc->flags |= FULL_INIT_DONE; done: if (rc != 0) adapter_full_uninit(sc); return (rc); } int adapter_full_uninit(struct adapter *sc) { int i; ADAPTER_LOCK_ASSERT_NOTOWNED(sc); t4_teardown_adapter_queues(sc); for (i = 0; i < nitems(sc->tq) && sc->tq[i]; i++) { taskqueue_free(sc->tq[i]); sc->tq[i] = NULL; } sc->flags &= ~FULL_INIT_DONE; return (0); } #ifdef RSS #define SUPPORTED_RSS_HASHTYPES (RSS_HASHTYPE_RSS_IPV4 | \ RSS_HASHTYPE_RSS_TCP_IPV4 | RSS_HASHTYPE_RSS_IPV6 | \ RSS_HASHTYPE_RSS_TCP_IPV6 | RSS_HASHTYPE_RSS_UDP_IPV4 | \ RSS_HASHTYPE_RSS_UDP_IPV6) /* Translates kernel hash types to hardware. */ static int hashconfig_to_hashen(int hashconfig) { int hashen = 0; if (hashconfig & RSS_HASHTYPE_RSS_IPV4) hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN; if (hashconfig & RSS_HASHTYPE_RSS_IPV6) hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN; if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV4) { hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN | F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; } if (hashconfig & RSS_HASHTYPE_RSS_UDP_IPV6) { hashen |= F_FW_RSS_VI_CONFIG_CMD_UDPEN | F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; } if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV4) hashen |= F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN; if (hashconfig & RSS_HASHTYPE_RSS_TCP_IPV6) hashen |= F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN; return (hashen); } /* Translates hardware hash types to kernel. */ static int hashen_to_hashconfig(int hashen) { int hashconfig = 0; if (hashen & F_FW_RSS_VI_CONFIG_CMD_UDPEN) { /* * If UDP hashing was enabled it must have been enabled for * either IPv4 or IPv6 (inclusive or). Enabling UDP without * enabling any 4-tuple hash is nonsense configuration. */ MPASS(hashen & (F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN)); if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV4; if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) hashconfig |= RSS_HASHTYPE_RSS_UDP_IPV6; } if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN) hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV4; if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN) hashconfig |= RSS_HASHTYPE_RSS_TCP_IPV6; if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN) hashconfig |= RSS_HASHTYPE_RSS_IPV4; if (hashen & F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN) hashconfig |= RSS_HASHTYPE_RSS_IPV6; return (hashconfig); } #endif int vi_full_init(struct vi_info *vi) { struct adapter *sc = vi->pi->adapter; struct ifnet *ifp = vi->ifp; uint16_t *rss; struct sge_rxq *rxq; int rc, i, j, hashen; #ifdef RSS int nbuckets = rss_getnumbuckets(); int hashconfig = rss_gethashconfig(); int extra; #endif ASSERT_SYNCHRONIZED_OP(sc); KASSERT((vi->flags & VI_INIT_DONE) == 0, ("%s: VI_INIT_DONE already", __func__)); sysctl_ctx_init(&vi->ctx); vi->flags |= VI_SYSCTL_CTX; /* * Allocate tx/rx/fl queues for this VI. */ rc = t4_setup_vi_queues(vi); if (rc != 0) goto done; /* error message displayed already */ /* * Setup RSS for this VI. Save a copy of the RSS table for later use. */ if (vi->nrxq > vi->rss_size) { if_printf(ifp, "nrxq (%d) > hw RSS table size (%d); " "some queues will never receive traffic.\n", vi->nrxq, vi->rss_size); } else if (vi->rss_size % vi->nrxq) { if_printf(ifp, "nrxq (%d), hw RSS table size (%d); " "expect uneven traffic distribution.\n", vi->nrxq, vi->rss_size); } #ifdef RSS if (vi->nrxq != nbuckets) { if_printf(ifp, "nrxq (%d) != kernel RSS buckets (%d);" "performance will be impacted.\n", vi->nrxq, nbuckets); } #endif rss = malloc(vi->rss_size * sizeof (*rss), M_CXGBE, M_ZERO | M_WAITOK); for (i = 0; i < vi->rss_size;) { #ifdef RSS j = rss_get_indirection_to_bucket(i); j %= vi->nrxq; rxq = &sc->sge.rxq[vi->first_rxq + j]; rss[i++] = rxq->iq.abs_id; #else for_each_rxq(vi, j, rxq) { rss[i++] = rxq->iq.abs_id; if (i == vi->rss_size) break; } #endif } rc = -t4_config_rss_range(sc, sc->mbox, vi->viid, 0, vi->rss_size, rss, vi->rss_size); if (rc != 0) { if_printf(ifp, "rss_config failed: %d\n", rc); goto done; } #ifdef RSS hashen = hashconfig_to_hashen(hashconfig); /* * We may have had to enable some hashes even though the global config * wants them disabled. This is a potential problem that must be * reported to the user. */ extra = hashen_to_hashconfig(hashen) ^ hashconfig; /* * If we consider only the supported hash types, then the enabled hashes * are a superset of the requested hashes. In other words, there cannot * be any supported hash that was requested but not enabled, but there * can be hashes that were not requested but had to be enabled. */ extra &= SUPPORTED_RSS_HASHTYPES; MPASS((extra & hashconfig) == 0); if (extra) { if_printf(ifp, "global RSS config (0x%x) cannot be accommodated.\n", hashconfig); } if (extra & RSS_HASHTYPE_RSS_IPV4) if_printf(ifp, "IPv4 2-tuple hashing forced on.\n"); if (extra & RSS_HASHTYPE_RSS_TCP_IPV4) if_printf(ifp, "TCP/IPv4 4-tuple hashing forced on.\n"); if (extra & RSS_HASHTYPE_RSS_IPV6) if_printf(ifp, "IPv6 2-tuple hashing forced on.\n"); if (extra & RSS_HASHTYPE_RSS_TCP_IPV6) if_printf(ifp, "TCP/IPv6 4-tuple hashing forced on.\n"); if (extra & RSS_HASHTYPE_RSS_UDP_IPV4) if_printf(ifp, "UDP/IPv4 4-tuple hashing forced on.\n"); if (extra & RSS_HASHTYPE_RSS_UDP_IPV6) if_printf(ifp, "UDP/IPv6 4-tuple hashing forced on.\n"); #else hashen = F_FW_RSS_VI_CONFIG_CMD_IP6FOURTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP6TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP4FOURTUPEN | F_FW_RSS_VI_CONFIG_CMD_IP4TWOTUPEN | F_FW_RSS_VI_CONFIG_CMD_UDPEN; #endif rc = -t4_config_vi_rss(sc, sc->mbox, vi->viid, hashen, rss[0], 0, 0); if (rc != 0) { if_printf(ifp, "rss hash/defaultq config failed: %d\n", rc); goto done; } vi->rss = rss; vi->flags |= VI_INIT_DONE; done: if (rc != 0) vi_full_uninit(vi); return (rc); } /* * Idempotent. */ int vi_full_uninit(struct vi_info *vi) { struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; int i; struct sge_rxq *rxq; struct sge_txq *txq; #ifdef TCP_OFFLOAD struct sge_ofld_rxq *ofld_rxq; struct sge_wrq *ofld_txq; #endif if (vi->flags & VI_INIT_DONE) { /* Need to quiesce queues. */ /* XXX: Only for the first VI? */ if (IS_MAIN_VI(vi) && !(sc->flags & IS_VF)) quiesce_wrq(sc, &sc->sge.ctrlq[pi->port_id]); for_each_txq(vi, i, txq) { quiesce_txq(sc, txq); } #ifdef TCP_OFFLOAD for_each_ofld_txq(vi, i, ofld_txq) { quiesce_wrq(sc, ofld_txq); } #endif for_each_rxq(vi, i, rxq) { quiesce_iq(sc, &rxq->iq); quiesce_fl(sc, &rxq->fl); } #ifdef TCP_OFFLOAD for_each_ofld_rxq(vi, i, ofld_rxq) { quiesce_iq(sc, &ofld_rxq->iq); quiesce_fl(sc, &ofld_rxq->fl); } #endif free(vi->rss, M_CXGBE); free(vi->nm_rss, M_CXGBE); } t4_teardown_vi_queues(vi); vi->flags &= ~VI_INIT_DONE; return (0); } static void quiesce_txq(struct adapter *sc, struct sge_txq *txq) { struct sge_eq *eq = &txq->eq; struct sge_qstat *spg = (void *)&eq->desc[eq->sidx]; (void) sc; /* unused */ #ifdef INVARIANTS TXQ_LOCK(txq); MPASS((eq->flags & EQ_ENABLED) == 0); TXQ_UNLOCK(txq); #endif /* Wait for the mp_ring to empty. */ while (!mp_ring_is_idle(txq->r)) { mp_ring_check_drainage(txq->r, 0); pause("rquiesce", 1); } /* Then wait for the hardware to finish. */ while (spg->cidx != htobe16(eq->pidx)) pause("equiesce", 1); /* Finally, wait for the driver to reclaim all descriptors. */ while (eq->cidx != eq->pidx) pause("dquiesce", 1); } static void quiesce_wrq(struct adapter *sc, struct sge_wrq *wrq) { /* XXXTX */ } static void quiesce_iq(struct adapter *sc, struct sge_iq *iq) { (void) sc; /* unused */ /* Synchronize with the interrupt handler */ while (!atomic_cmpset_int(&iq->state, IQS_IDLE, IQS_DISABLED)) pause("iqfree", 1); } static void quiesce_fl(struct adapter *sc, struct sge_fl *fl) { mtx_lock(&sc->sfl_lock); FL_LOCK(fl); fl->flags |= FL_DOOMED; FL_UNLOCK(fl); callout_stop(&sc->sfl_callout); mtx_unlock(&sc->sfl_lock); KASSERT((fl->flags & FL_STARVING) == 0, ("%s: still starving", __func__)); } static int t4_alloc_irq(struct adapter *sc, struct irq *irq, int rid, driver_intr_t *handler, void *arg, char *name) { int rc; irq->rid = rid; irq->res = bus_alloc_resource_any(sc->dev, SYS_RES_IRQ, &irq->rid, RF_SHAREABLE | RF_ACTIVE); if (irq->res == NULL) { device_printf(sc->dev, "failed to allocate IRQ for rid %d, name %s.\n", rid, name); return (ENOMEM); } rc = bus_setup_intr(sc->dev, irq->res, INTR_MPSAFE | INTR_TYPE_NET, NULL, handler, arg, &irq->tag); if (rc != 0) { device_printf(sc->dev, "failed to setup interrupt for rid %d, name %s: %d\n", rid, name, rc); } else if (name) bus_describe_intr(sc->dev, irq->res, irq->tag, "%s", name); return (rc); } static int t4_free_irq(struct adapter *sc, struct irq *irq) { if (irq->tag) bus_teardown_intr(sc->dev, irq->res, irq->tag); if (irq->res) bus_release_resource(sc->dev, SYS_RES_IRQ, irq->rid, irq->res); bzero(irq, sizeof(*irq)); return (0); } static void get_regs(struct adapter *sc, struct t4_regdump *regs, uint8_t *buf) { regs->version = chip_id(sc) | chip_rev(sc) << 10; t4_get_regs(sc, buf, regs->len); } #define A_PL_INDIR_CMD 0x1f8 #define S_PL_AUTOINC 31 #define M_PL_AUTOINC 0x1U #define V_PL_AUTOINC(x) ((x) << S_PL_AUTOINC) #define G_PL_AUTOINC(x) (((x) >> S_PL_AUTOINC) & M_PL_AUTOINC) #define S_PL_VFID 20 #define M_PL_VFID 0xffU #define V_PL_VFID(x) ((x) << S_PL_VFID) #define G_PL_VFID(x) (((x) >> S_PL_VFID) & M_PL_VFID) #define S_PL_ADDR 0 #define M_PL_ADDR 0xfffffU #define V_PL_ADDR(x) ((x) << S_PL_ADDR) #define G_PL_ADDR(x) (((x) >> S_PL_ADDR) & M_PL_ADDR) #define A_PL_INDIR_DATA 0x1fc static uint64_t read_vf_stat(struct adapter *sc, unsigned int viid, int reg) { u32 stats[2]; mtx_assert(&sc->reg_lock, MA_OWNED); if (sc->flags & IS_VF) { stats[0] = t4_read_reg(sc, VF_MPS_REG(reg)); stats[1] = t4_read_reg(sc, VF_MPS_REG(reg + 4)); } else { t4_write_reg(sc, A_PL_INDIR_CMD, V_PL_AUTOINC(1) | V_PL_VFID(G_FW_VIID_VIN(viid)) | V_PL_ADDR(VF_MPS_REG(reg))); stats[0] = t4_read_reg(sc, A_PL_INDIR_DATA); stats[1] = t4_read_reg(sc, A_PL_INDIR_DATA); } return (((uint64_t)stats[1]) << 32 | stats[0]); } static void t4_get_vi_stats(struct adapter *sc, unsigned int viid, struct fw_vi_stats_vf *stats) { #define GET_STAT(name) \ read_vf_stat(sc, viid, A_MPS_VF_STAT_##name##_L) stats->tx_bcast_bytes = GET_STAT(TX_VF_BCAST_BYTES); stats->tx_bcast_frames = GET_STAT(TX_VF_BCAST_FRAMES); stats->tx_mcast_bytes = GET_STAT(TX_VF_MCAST_BYTES); stats->tx_mcast_frames = GET_STAT(TX_VF_MCAST_FRAMES); stats->tx_ucast_bytes = GET_STAT(TX_VF_UCAST_BYTES); stats->tx_ucast_frames = GET_STAT(TX_VF_UCAST_FRAMES); stats->tx_drop_frames = GET_STAT(TX_VF_DROP_FRAMES); stats->tx_offload_bytes = GET_STAT(TX_VF_OFFLOAD_BYTES); stats->tx_offload_frames = GET_STAT(TX_VF_OFFLOAD_FRAMES); stats->rx_bcast_bytes = GET_STAT(RX_VF_BCAST_BYTES); stats->rx_bcast_frames = GET_STAT(RX_VF_BCAST_FRAMES); stats->rx_mcast_bytes = GET_STAT(RX_VF_MCAST_BYTES); stats->rx_mcast_frames = GET_STAT(RX_VF_MCAST_FRAMES); stats->rx_ucast_bytes = GET_STAT(RX_VF_UCAST_BYTES); stats->rx_ucast_frames = GET_STAT(RX_VF_UCAST_FRAMES); stats->rx_err_frames = GET_STAT(RX_VF_ERR_FRAMES); #undef GET_STAT } static void t4_clr_vi_stats(struct adapter *sc, unsigned int viid) { int reg; t4_write_reg(sc, A_PL_INDIR_CMD, V_PL_AUTOINC(1) | V_PL_VFID(G_FW_VIID_VIN(viid)) | V_PL_ADDR(VF_MPS_REG(A_MPS_VF_STAT_TX_VF_BCAST_BYTES_L))); for (reg = A_MPS_VF_STAT_TX_VF_BCAST_BYTES_L; reg <= A_MPS_VF_STAT_RX_VF_ERR_FRAMES_H; reg += 4) t4_write_reg(sc, A_PL_INDIR_DATA, 0); } static void vi_refresh_stats(struct adapter *sc, struct vi_info *vi) { struct timeval tv; const struct timeval interval = {0, 250000}; /* 250ms */ if (!(vi->flags & VI_INIT_DONE)) return; getmicrotime(&tv); timevalsub(&tv, &interval); if (timevalcmp(&tv, &vi->last_refreshed, <)) return; mtx_lock(&sc->reg_lock); t4_get_vi_stats(sc, vi->viid, &vi->stats); getmicrotime(&vi->last_refreshed); mtx_unlock(&sc->reg_lock); } static void cxgbe_refresh_stats(struct adapter *sc, struct port_info *pi) { int i; u_int v, tnl_cong_drops; struct timeval tv; const struct timeval interval = {0, 250000}; /* 250ms */ getmicrotime(&tv); timevalsub(&tv, &interval); if (timevalcmp(&tv, &pi->last_refreshed, <)) return; tnl_cong_drops = 0; t4_get_port_stats(sc, pi->tx_chan, &pi->stats); for (i = 0; i < sc->chip_params->nchan; i++) { if (pi->rx_chan_map & (1 << i)) { mtx_lock(&sc->reg_lock); t4_read_indirect(sc, A_TP_MIB_INDEX, A_TP_MIB_DATA, &v, 1, A_TP_MIB_TNL_CNG_DROP_0 + i); mtx_unlock(&sc->reg_lock); tnl_cong_drops += v; } } pi->tnl_cong_drops = tnl_cong_drops; getmicrotime(&pi->last_refreshed); } static void cxgbe_tick(void *arg) { struct port_info *pi = arg; struct adapter *sc = pi->adapter; PORT_LOCK_ASSERT_OWNED(pi); cxgbe_refresh_stats(sc, pi); callout_schedule(&pi->tick, hz); } void vi_tick(void *arg) { struct vi_info *vi = arg; struct adapter *sc = vi->pi->adapter; vi_refresh_stats(sc, vi); callout_schedule(&vi->tick, hz); } static void cxgbe_vlan_config(void *arg, struct ifnet *ifp, uint16_t vid) { struct ifnet *vlan; if (arg != ifp || ifp->if_type != IFT_ETHER) return; vlan = VLAN_DEVAT(ifp, vid); VLAN_SETCOOKIE(vlan, ifp); } /* * Should match fw_caps_config_ enums in t4fw_interface.h */ static char *caps_decoder[] = { "\20\001IPMI\002NCSI", /* 0: NBM */ "\20\001PPP\002QFC\003DCBX", /* 1: link */ "\20\001INGRESS\002EGRESS", /* 2: switch */ "\20\001NIC\002VM\003IDS\004UM\005UM_ISGL" /* 3: NIC */ "\006HASHFILTER\007ETHOFLD", "\20\001TOE", /* 4: TOE */ "\20\001RDDP\002RDMAC", /* 5: RDMA */ "\20\001INITIATOR_PDU\002TARGET_PDU" /* 6: iSCSI */ "\003INITIATOR_CNXOFLD\004TARGET_CNXOFLD" "\005INITIATOR_SSNOFLD\006TARGET_SSNOFLD" "\007T10DIF" "\010INITIATOR_CMDOFLD\011TARGET_CMDOFLD", "\20\001LOOKASIDE\002TLSKEYS", /* 7: Crypto */ "\20\001INITIATOR\002TARGET\003CTRL_OFLD" /* 8: FCoE */ "\004PO_INITIATOR\005PO_TARGET", }; void t4_sysctls(struct adapter *sc) { struct sysctl_ctx_list *ctx; struct sysctl_oid *oid; struct sysctl_oid_list *children, *c0; static char *doorbells = {"\20\1UDB\2WCWR\3UDBWC\4KDB"}; ctx = device_get_sysctl_ctx(sc->dev); /* * dev.t4nex.X. */ oid = device_get_sysctl_tree(sc->dev); c0 = children = SYSCTL_CHILDREN(oid); sc->sc_do_rxcopy = 1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "do_rx_copy", CTLFLAG_RW, &sc->sc_do_rxcopy, 1, "Do RX copy of small frames"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nports", CTLFLAG_RD, NULL, sc->params.nports, "# of ports"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "doorbells", CTLTYPE_STRING | CTLFLAG_RD, doorbells, sc->doorbells, sysctl_bitfield, "A", "available doorbells"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "core_clock", CTLFLAG_RD, NULL, sc->params.vpd.cclk, "core clock frequency (in KHz)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "holdoff_timers", CTLTYPE_STRING | CTLFLAG_RD, sc->params.sge.timer_val, sizeof(sc->params.sge.timer_val), sysctl_int_array, "A", "interrupt holdoff timer values (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "holdoff_pkt_counts", CTLTYPE_STRING | CTLFLAG_RD, sc->params.sge.counter_val, sizeof(sc->params.sge.counter_val), sysctl_int_array, "A", "interrupt holdoff packet counter values"); t4_sge_sysctls(sc, ctx, children); sc->lro_timeout = 100; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "lro_timeout", CTLFLAG_RW, &sc->lro_timeout, 0, "lro inactive-flush timeout (in us)"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "dflags", CTLFLAG_RW, &sc->debug_flags, 0, "flags to enable runtime debugging"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "tp_version", CTLFLAG_RD, sc->tp_version, 0, "TP microcode version"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "firmware_version", CTLFLAG_RD, sc->fw_version, 0, "firmware version"); if (sc->flags & IS_VF) return; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "hw_revision", CTLFLAG_RD, NULL, chip_rev(sc), "chip hardware revision"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "sn", CTLFLAG_RD, sc->params.vpd.sn, 0, "serial number"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "pn", CTLFLAG_RD, sc->params.vpd.pn, 0, "part number"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "ec", CTLFLAG_RD, sc->params.vpd.ec, 0, "engineering change"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "na", CTLFLAG_RD, sc->params.vpd.na, 0, "network address"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "er_version", CTLFLAG_RD, sc->er_version, 0, "expansion ROM version"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "bs_version", CTLFLAG_RD, sc->bs_version, 0, "bootstrap firmware version"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "scfg_version", CTLFLAG_RD, NULL, sc->params.scfg_vers, "serial config version"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "vpd_version", CTLFLAG_RD, NULL, sc->params.vpd_vers, "VPD version"); SYSCTL_ADD_STRING(ctx, children, OID_AUTO, "cf", CTLFLAG_RD, sc->cfg_file, 0, "configuration file"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "cfcsum", CTLFLAG_RD, NULL, sc->cfcsum, "config file checksum"); #define SYSCTL_CAP(name, n, text) \ SYSCTL_ADD_PROC(ctx, children, OID_AUTO, #name, \ CTLTYPE_STRING | CTLFLAG_RD, caps_decoder[n], sc->name, \ sysctl_bitfield, "A", "available " text " capabilities") SYSCTL_CAP(nbmcaps, 0, "NBM"); SYSCTL_CAP(linkcaps, 1, "link"); SYSCTL_CAP(switchcaps, 2, "switch"); SYSCTL_CAP(niccaps, 3, "NIC"); SYSCTL_CAP(toecaps, 4, "TCP offload"); SYSCTL_CAP(rdmacaps, 5, "RDMA"); SYSCTL_CAP(iscsicaps, 6, "iSCSI"); SYSCTL_CAP(cryptocaps, 7, "crypto"); SYSCTL_CAP(fcoecaps, 8, "FCoE"); #undef SYSCTL_CAP SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nfilters", CTLFLAG_RD, NULL, sc->tids.nftids, "number of filters"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, sc, 0, sysctl_temperature, "I", "chip temperature (in Celsius)"); #ifdef SBUF_DRAIN /* * dev.t4nex.X.misc. Marked CTLFLAG_SKIP to avoid information overload. */ oid = SYSCTL_ADD_NODE(ctx, c0, OID_AUTO, "misc", CTLFLAG_RD | CTLFLAG_SKIP, NULL, "logs and miscellaneous information"); children = SYSCTL_CHILDREN(oid); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cctrl", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cctrl, "A", "congestion control"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_tp0", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cim_ibq_obq, "A", "CIM IBQ 0 (TP0)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_tp1", CTLTYPE_STRING | CTLFLAG_RD, sc, 1, sysctl_cim_ibq_obq, "A", "CIM IBQ 1 (TP1)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_ulp", CTLTYPE_STRING | CTLFLAG_RD, sc, 2, sysctl_cim_ibq_obq, "A", "CIM IBQ 2 (ULP)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_sge0", CTLTYPE_STRING | CTLFLAG_RD, sc, 3, sysctl_cim_ibq_obq, "A", "CIM IBQ 3 (SGE0)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_sge1", CTLTYPE_STRING | CTLFLAG_RD, sc, 4, sysctl_cim_ibq_obq, "A", "CIM IBQ 4 (SGE1)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ibq_ncsi", CTLTYPE_STRING | CTLFLAG_RD, sc, 5, sysctl_cim_ibq_obq, "A", "CIM IBQ 5 (NCSI)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_la", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, chip_id(sc) <= CHELSIO_T5 ? sysctl_cim_la : sysctl_cim_la_t6, "A", "CIM logic analyzer"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_ma_la", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cim_ma_la, "A", "CIM MA logic analyzer"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp0", CTLTYPE_STRING | CTLFLAG_RD, sc, 0 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 0 (ULP0)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp1", CTLTYPE_STRING | CTLFLAG_RD, sc, 1 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 1 (ULP1)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp2", CTLTYPE_STRING | CTLFLAG_RD, sc, 2 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 2 (ULP2)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ulp3", CTLTYPE_STRING | CTLFLAG_RD, sc, 3 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 3 (ULP3)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_sge", CTLTYPE_STRING | CTLFLAG_RD, sc, 4 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 4 (SGE)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_ncsi", CTLTYPE_STRING | CTLFLAG_RD, sc, 5 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 5 (NCSI)"); if (chip_id(sc) > CHELSIO_T4) { SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_sge0_rx", CTLTYPE_STRING | CTLFLAG_RD, sc, 6 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 6 (SGE0-RX)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_obq_sge1_rx", CTLTYPE_STRING | CTLFLAG_RD, sc, 7 + CIM_NUM_IBQ, sysctl_cim_ibq_obq, "A", "CIM OBQ 7 (SGE1-RX)"); } SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_pif_la", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cim_pif_la, "A", "CIM PIF logic analyzer"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cim_qcfg", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cim_qcfg, "A", "CIM queue configuration"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "cpl_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_cpl_stats, "A", "CPL statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "ddp_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_ddp_stats, "A", "non-TCP DDP statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "devlog", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_devlog, "A", "firmware's device log"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fcoe_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_fcoe_stats, "A", "FCoE statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "hw_sched", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_hw_sched, "A", "hardware scheduler "); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "l2t", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_l2t, "A", "hardware L2 table"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "lb_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_lb_stats, "A", "loopback statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "meminfo", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_meminfo, "A", "memory regions"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "mps_tcam", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, chip_id(sc) <= CHELSIO_T5 ? sysctl_mps_tcam : sysctl_mps_tcam_t6, "A", "MPS TCAM entries"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "path_mtus", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_path_mtus, "A", "path MTUs"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "pm_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_pm_stats, "A", "PM statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rdma_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_rdma_stats, "A", "RDMA statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tcp_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tcp_stats, "A", "TCP statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tids", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tids, "A", "TID information"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tp_err_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tp_err_stats, "A", "TP error statistics"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tp_la_mask", CTLTYPE_INT | CTLFLAG_RW, sc, 0, sysctl_tp_la_mask, "I", "TP logic analyzer event capture mask"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tp_la", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tp_la, "A", "TP logic analyzer"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "tx_rate", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tx_rate, "A", "Tx rate"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "ulprx_la", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_ulprx_la, "A", "ULPRX logic analyzer"); if (chip_id(sc) >= CHELSIO_T5) { SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "wcwr_stats", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_wcwr_stats, "A", "write combined work requests"); } #endif #ifdef TCP_OFFLOAD if (is_offload(sc)) { int i; char s[4]; /* * dev.t4nex.X.toe. */ oid = SYSCTL_ADD_NODE(ctx, c0, OID_AUTO, "toe", CTLFLAG_RD, NULL, "TOE parameters"); children = SYSCTL_CHILDREN(oid); sc->tt.sndbuf = 256 * 1024; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "sndbuf", CTLFLAG_RW, &sc->tt.sndbuf, 0, "max hardware send buffer size"); sc->tt.ddp = 0; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ddp", CTLFLAG_RW, &sc->tt.ddp, 0, "DDP allowed"); sc->tt.rx_coalesce = 1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "rx_coalesce", CTLFLAG_RW, &sc->tt.rx_coalesce, 0, "receive coalescing"); sc->tt.tx_align = 1; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_align", CTLFLAG_RW, &sc->tt.tx_align, 0, "chop and align payload"); sc->tt.tx_zcopy = 0; SYSCTL_ADD_INT(ctx, children, OID_AUTO, "tx_zcopy", CTLFLAG_RW, &sc->tt.tx_zcopy, 0, "Enable zero-copy aio_write(2)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "timer_tick", CTLTYPE_STRING | CTLFLAG_RD, sc, 0, sysctl_tp_tick, "A", "TP timer tick (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "timestamp_tick", CTLTYPE_STRING | CTLFLAG_RD, sc, 1, sysctl_tp_tick, "A", "TCP timestamp tick (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dack_tick", CTLTYPE_STRING | CTLFLAG_RD, sc, 2, sysctl_tp_tick, "A", "DACK tick (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "dack_timer", CTLTYPE_UINT | CTLFLAG_RD, sc, 0, sysctl_tp_dack_timer, "IU", "DACK timer (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rexmt_min", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_RXT_MIN, sysctl_tp_timer, "LU", "Minimum retransmit interval (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rexmt_max", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_RXT_MAX, sysctl_tp_timer, "LU", "Maximum retransmit interval (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "persist_min", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_PERS_MIN, sysctl_tp_timer, "LU", "Persist timer min (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "persist_max", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_PERS_MAX, sysctl_tp_timer, "LU", "Persist timer max (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "keepalive_idle", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_KEEP_IDLE, sysctl_tp_timer, "LU", "Keepalive idle timer (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "keepalive_interval", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_KEEP_INTVL, sysctl_tp_timer, "LU", "Keepalive interval timer (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "initial_srtt", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_INIT_SRTT, sysctl_tp_timer, "LU", "Initial SRTT (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "finwait2_timer", CTLTYPE_ULONG | CTLFLAG_RD, sc, A_TP_FINWAIT2_TIMER, sysctl_tp_timer, "LU", "FINWAIT2 timer (us)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "syn_rexmt_count", CTLTYPE_UINT | CTLFLAG_RD, sc, S_SYNSHIFTMAX, sysctl_tp_shift_cnt, "IU", "Number of SYN retransmissions before abort"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rexmt_count", CTLTYPE_UINT | CTLFLAG_RD, sc, S_RXTSHIFTMAXR2, sysctl_tp_shift_cnt, "IU", "Number of retransmissions before abort"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "keepalive_count", CTLTYPE_UINT | CTLFLAG_RD, sc, S_KEEPALIVEMAXR2, sysctl_tp_shift_cnt, "IU", "Number of keepalive probes before abort"); oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "rexmt_backoff", CTLFLAG_RD, NULL, "TOE retransmit backoffs"); children = SYSCTL_CHILDREN(oid); for (i = 0; i < 16; i++) { snprintf(s, sizeof(s), "%u", i); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, s, CTLTYPE_UINT | CTLFLAG_RD, sc, i, sysctl_tp_backoff, "IU", "TOE retransmit backoff"); } } #endif } void vi_sysctls(struct vi_info *vi) { struct sysctl_ctx_list *ctx; struct sysctl_oid *oid; struct sysctl_oid_list *children; ctx = device_get_sysctl_ctx(vi->dev); /* * dev.v?(cxgbe|cxl).X. */ oid = device_get_sysctl_tree(vi->dev); children = SYSCTL_CHILDREN(oid); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "viid", CTLFLAG_RD, NULL, vi->viid, "VI identifer"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nrxq", CTLFLAG_RD, &vi->nrxq, 0, "# of rx queues"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "ntxq", CTLFLAG_RD, &vi->ntxq, 0, "# of tx queues"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_rxq", CTLFLAG_RD, &vi->first_rxq, 0, "index of first rx queue"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_txq", CTLFLAG_RD, &vi->first_txq, 0, "index of first tx queue"); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "rss_size", CTLFLAG_RD, NULL, vi->rss_size, "size of RSS indirection table"); if (IS_MAIN_VI(vi)) { SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "rsrv_noflowq", CTLTYPE_INT | CTLFLAG_RW, vi, 0, sysctl_noflowq, "IU", "Reserve queue 0 for non-flowid packets"); } #ifdef TCP_OFFLOAD if (vi->nofldrxq != 0) { SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nofldrxq", CTLFLAG_RD, &vi->nofldrxq, 0, "# of rx queues for offloaded TCP connections"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nofldtxq", CTLFLAG_RD, &vi->nofldtxq, 0, "# of tx queues for offloaded TCP connections"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_ofld_rxq", CTLFLAG_RD, &vi->first_ofld_rxq, 0, "index of first TOE rx queue"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_ofld_txq", CTLFLAG_RD, &vi->first_ofld_txq, 0, "index of first TOE tx queue"); } #endif #ifdef DEV_NETMAP if (vi->nnmrxq != 0) { SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nnmrxq", CTLFLAG_RD, &vi->nnmrxq, 0, "# of netmap rx queues"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "nnmtxq", CTLFLAG_RD, &vi->nnmtxq, 0, "# of netmap tx queues"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_nm_rxq", CTLFLAG_RD, &vi->first_nm_rxq, 0, "index of first netmap rx queue"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "first_nm_txq", CTLFLAG_RD, &vi->first_nm_txq, 0, "index of first netmap tx queue"); } #endif SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "holdoff_tmr_idx", CTLTYPE_INT | CTLFLAG_RW, vi, 0, sysctl_holdoff_tmr_idx, "I", "holdoff timer index"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "holdoff_pktc_idx", CTLTYPE_INT | CTLFLAG_RW, vi, 0, sysctl_holdoff_pktc_idx, "I", "holdoff packet counter index"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "qsize_rxq", CTLTYPE_INT | CTLFLAG_RW, vi, 0, sysctl_qsize_rxq, "I", "rx queue size"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "qsize_txq", CTLTYPE_INT | CTLFLAG_RW, vi, 0, sysctl_qsize_txq, "I", "tx queue size"); } static void cxgbe_sysctls(struct port_info *pi) { struct sysctl_ctx_list *ctx; struct sysctl_oid *oid; struct sysctl_oid_list *children, *children2; struct adapter *sc = pi->adapter; int i; char name[16]; ctx = device_get_sysctl_ctx(pi->dev); /* * dev.cxgbe.X. */ oid = device_get_sysctl_tree(pi->dev); children = SYSCTL_CHILDREN(oid); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "linkdnrc", CTLTYPE_STRING | CTLFLAG_RD, pi, 0, sysctl_linkdnrc, "A", "reason why link is down"); if (pi->port_type == FW_PORT_TYPE_BT_XAUI) { SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "temperature", CTLTYPE_INT | CTLFLAG_RD, pi, 0, sysctl_btphy, "I", "PHY temperature (in Celsius)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fw_version", CTLTYPE_INT | CTLFLAG_RD, pi, 1, sysctl_btphy, "I", "PHY firmware version"); } SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "pause_settings", CTLTYPE_STRING | CTLFLAG_RW, pi, 0, sysctl_pause_settings, "A", "PAUSE settings (bit 0 = rx_pause, bit 1 = tx_pause)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "fec", CTLTYPE_STRING | CTLFLAG_RW, pi, 0, sysctl_fec, "A", "Forward Error Correction (bit 0 = RS, bit 1 = BASER_RS)"); SYSCTL_ADD_PROC(ctx, children, OID_AUTO, "autoneg", CTLTYPE_INT | CTLFLAG_RW, pi, 0, sysctl_autoneg, "I", "autonegotiation (-1 = not supported)"); SYSCTL_ADD_INT(ctx, children, OID_AUTO, "max_speed", CTLFLAG_RD, NULL, port_top_speed(pi), "max speed (in Gbps)"); if (sc->flags & IS_VF) return; /* * dev.(cxgbe|cxl).X.tc. */ oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "tc", CTLFLAG_RD, NULL, "Tx scheduler traffic classes (cl_rl)"); for (i = 0; i < sc->chip_params->nsched_cls; i++) { struct tx_cl_rl_params *tc = &pi->sched_params->cl_rl[i]; snprintf(name, sizeof(name), "%d", i); children2 = SYSCTL_CHILDREN(SYSCTL_ADD_NODE(ctx, SYSCTL_CHILDREN(oid), OID_AUTO, name, CTLFLAG_RD, NULL, "traffic class")); SYSCTL_ADD_UINT(ctx, children2, OID_AUTO, "flags", CTLFLAG_RD, &tc->flags, 0, "flags"); SYSCTL_ADD_UINT(ctx, children2, OID_AUTO, "refcount", CTLFLAG_RD, &tc->refcount, 0, "references to this class"); #ifdef SBUF_DRAIN SYSCTL_ADD_PROC(ctx, children2, OID_AUTO, "params", CTLTYPE_STRING | CTLFLAG_RD, sc, (pi->port_id << 16) | i, sysctl_tc_params, "A", "traffic class parameters"); #endif } /* * dev.cxgbe.X.stats. */ oid = SYSCTL_ADD_NODE(ctx, children, OID_AUTO, "stats", CTLFLAG_RD, NULL, "port statistics"); children = SYSCTL_CHILDREN(oid); SYSCTL_ADD_UINT(ctx, children, OID_AUTO, "tx_parse_error", CTLFLAG_RD, &pi->tx_parse_error, 0, "# of tx packets with invalid length or # of segments"); #define SYSCTL_ADD_T4_REG64(pi, name, desc, reg) \ SYSCTL_ADD_OID(ctx, children, OID_AUTO, name, \ CTLTYPE_U64 | CTLFLAG_RD, sc, reg, \ sysctl_handle_t4_reg64, "QU", desc) SYSCTL_ADD_T4_REG64(pi, "tx_octets", "# of octets in good frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_BYTES_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames", "total # of good frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_FRAMES_L)); SYSCTL_ADD_T4_REG64(pi, "tx_bcast_frames", "# of broadcast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_BCAST_L)); SYSCTL_ADD_T4_REG64(pi, "tx_mcast_frames", "# of multicast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_MCAST_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ucast_frames", "# of unicast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_UCAST_L)); SYSCTL_ADD_T4_REG64(pi, "tx_error_frames", "# of error frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_64", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_64B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_65_127", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_65B_127B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_128_255", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_128B_255B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_256_511", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_256B_511B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_512_1023", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_512B_1023B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_1024_1518", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_1024B_1518B_L)); SYSCTL_ADD_T4_REG64(pi, "tx_frames_1519_max", "# of tx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_1519B_MAX_L)); SYSCTL_ADD_T4_REG64(pi, "tx_drop", "# of dropped tx frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_DROP_L)); SYSCTL_ADD_T4_REG64(pi, "tx_pause", "# of pause frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PAUSE_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp0", "# of PPP prio 0 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP0_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp1", "# of PPP prio 1 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP1_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp2", "# of PPP prio 2 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP2_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp3", "# of PPP prio 3 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP3_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp4", "# of PPP prio 4 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP4_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp5", "# of PPP prio 5 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP5_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp6", "# of PPP prio 6 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP6_L)); SYSCTL_ADD_T4_REG64(pi, "tx_ppp7", "# of PPP prio 7 frames transmitted", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_TX_PORT_PPP7_L)); SYSCTL_ADD_T4_REG64(pi, "rx_octets", "# of octets in good frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_BYTES_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames", "total # of good frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_FRAMES_L)); SYSCTL_ADD_T4_REG64(pi, "rx_bcast_frames", "# of broadcast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_BCAST_L)); SYSCTL_ADD_T4_REG64(pi, "rx_mcast_frames", "# of multicast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_MCAST_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ucast_frames", "# of unicast frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_UCAST_L)); SYSCTL_ADD_T4_REG64(pi, "rx_too_long", "# of frames exceeding MTU", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_MTU_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "rx_jabber", "# of jabber frames", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_MTU_CRC_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "rx_fcs_err", "# of frames received with bad FCS", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_CRC_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "rx_len_err", "# of frames received with length error", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_LEN_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "rx_symbol_err", "symbol errors", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_SYM_ERROR_L)); SYSCTL_ADD_T4_REG64(pi, "rx_runt", "# of short frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_LESS_64B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_64", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_64B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_65_127", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_65B_127B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_128_255", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_128B_255B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_256_511", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_256B_511B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_512_1023", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_512B_1023B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_1024_1518", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_1024B_1518B_L)); SYSCTL_ADD_T4_REG64(pi, "rx_frames_1519_max", "# of rx frames in this range", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_1519B_MAX_L)); SYSCTL_ADD_T4_REG64(pi, "rx_pause", "# of pause frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PAUSE_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp0", "# of PPP prio 0 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP0_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp1", "# of PPP prio 1 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP1_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp2", "# of PPP prio 2 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP2_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp3", "# of PPP prio 3 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP3_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp4", "# of PPP prio 4 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP4_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp5", "# of PPP prio 5 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP5_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp6", "# of PPP prio 6 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP6_L)); SYSCTL_ADD_T4_REG64(pi, "rx_ppp7", "# of PPP prio 7 frames received", PORT_REG(pi->tx_chan, A_MPS_PORT_STAT_RX_PORT_PPP7_L)); #undef SYSCTL_ADD_T4_REG64 #define SYSCTL_ADD_T4_PORTSTAT(name, desc) \ SYSCTL_ADD_UQUAD(ctx, children, OID_AUTO, #name, CTLFLAG_RD, \ &pi->stats.name, desc) /* We get these from port_stats and they may be stale by up to 1s */ SYSCTL_ADD_T4_PORTSTAT(rx_ovflow0, "# drops due to buffer-group 0 overflows"); SYSCTL_ADD_T4_PORTSTAT(rx_ovflow1, "# drops due to buffer-group 1 overflows"); SYSCTL_ADD_T4_PORTSTAT(rx_ovflow2, "# drops due to buffer-group 2 overflows"); SYSCTL_ADD_T4_PORTSTAT(rx_ovflow3, "# drops due to buffer-group 3 overflows"); SYSCTL_ADD_T4_PORTSTAT(rx_trunc0, "# of buffer-group 0 truncated packets"); SYSCTL_ADD_T4_PORTSTAT(rx_trunc1, "# of buffer-group 1 truncated packets"); SYSCTL_ADD_T4_PORTSTAT(rx_trunc2, "# of buffer-group 2 truncated packets"); SYSCTL_ADD_T4_PORTSTAT(rx_trunc3, "# of buffer-group 3 truncated packets"); #undef SYSCTL_ADD_T4_PORTSTAT } static int sysctl_int_array(SYSCTL_HANDLER_ARGS) { int rc, *i, space = 0; struct sbuf sb; sbuf_new_for_sysctl(&sb, NULL, 64, req); for (i = arg1; arg2; arg2 -= sizeof(int), i++) { if (space) sbuf_printf(&sb, " "); sbuf_printf(&sb, "%d", *i); space = 1; } rc = sbuf_finish(&sb); sbuf_delete(&sb); return (rc); } static int sysctl_bitfield(SYSCTL_HANDLER_ARGS) { int rc; struct sbuf *sb; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return(rc); sb = sbuf_new_for_sysctl(NULL, NULL, 128, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, "%b", (int)arg2, (char *)arg1); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_btphy(SYSCTL_HANDLER_ARGS) { struct port_info *pi = arg1; int op = arg2; struct adapter *sc = pi->adapter; u_int v; int rc; rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK, "t4btt"); if (rc) return (rc); /* XXX: magic numbers */ rc = -t4_mdio_rd(sc, sc->mbox, pi->mdio_addr, 0x1e, op ? 0x20 : 0xc820, &v); end_synchronized_op(sc, 0); if (rc) return (rc); if (op == 0) v /= 256; rc = sysctl_handle_int(oidp, &v, 0, req); return (rc); } static int sysctl_noflowq(SYSCTL_HANDLER_ARGS) { struct vi_info *vi = arg1; int rc, val; val = vi->rsrv_noflowq; rc = sysctl_handle_int(oidp, &val, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if ((val >= 1) && (vi->ntxq > 1)) vi->rsrv_noflowq = 1; else vi->rsrv_noflowq = 0; return (rc); } static int sysctl_holdoff_tmr_idx(SYSCTL_HANDLER_ARGS) { struct vi_info *vi = arg1; struct adapter *sc = vi->pi->adapter; int idx, rc, i; struct sge_rxq *rxq; #ifdef TCP_OFFLOAD struct sge_ofld_rxq *ofld_rxq; #endif uint8_t v; idx = vi->tmr_idx; rc = sysctl_handle_int(oidp, &idx, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if (idx < 0 || idx >= SGE_NTIMERS) return (EINVAL); rc = begin_synchronized_op(sc, vi, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4tmr"); if (rc) return (rc); v = V_QINTR_TIMER_IDX(idx) | V_QINTR_CNT_EN(vi->pktc_idx != -1); for_each_rxq(vi, i, rxq) { #ifdef atomic_store_rel_8 atomic_store_rel_8(&rxq->iq.intr_params, v); #else rxq->iq.intr_params = v; #endif } #ifdef TCP_OFFLOAD for_each_ofld_rxq(vi, i, ofld_rxq) { #ifdef atomic_store_rel_8 atomic_store_rel_8(&ofld_rxq->iq.intr_params, v); #else ofld_rxq->iq.intr_params = v; #endif } #endif vi->tmr_idx = idx; end_synchronized_op(sc, LOCK_HELD); return (0); } static int sysctl_holdoff_pktc_idx(SYSCTL_HANDLER_ARGS) { struct vi_info *vi = arg1; struct adapter *sc = vi->pi->adapter; int idx, rc; idx = vi->pktc_idx; rc = sysctl_handle_int(oidp, &idx, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if (idx < -1 || idx >= SGE_NCOUNTERS) return (EINVAL); rc = begin_synchronized_op(sc, vi, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4pktc"); if (rc) return (rc); if (vi->flags & VI_INIT_DONE) rc = EBUSY; /* cannot be changed once the queues are created */ else vi->pktc_idx = idx; end_synchronized_op(sc, LOCK_HELD); return (rc); } static int sysctl_qsize_rxq(SYSCTL_HANDLER_ARGS) { struct vi_info *vi = arg1; struct adapter *sc = vi->pi->adapter; int qsize, rc; qsize = vi->qsize_rxq; rc = sysctl_handle_int(oidp, &qsize, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if (qsize < 128 || (qsize & 7)) return (EINVAL); rc = begin_synchronized_op(sc, vi, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4rxqs"); if (rc) return (rc); if (vi->flags & VI_INIT_DONE) rc = EBUSY; /* cannot be changed once the queues are created */ else vi->qsize_rxq = qsize; end_synchronized_op(sc, LOCK_HELD); return (rc); } static int sysctl_qsize_txq(SYSCTL_HANDLER_ARGS) { struct vi_info *vi = arg1; struct adapter *sc = vi->pi->adapter; int qsize, rc; qsize = vi->qsize_txq; rc = sysctl_handle_int(oidp, &qsize, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if (qsize < 128 || qsize > 65536) return (EINVAL); rc = begin_synchronized_op(sc, vi, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4txqs"); if (rc) return (rc); if (vi->flags & VI_INIT_DONE) rc = EBUSY; /* cannot be changed once the queues are created */ else vi->qsize_txq = qsize; end_synchronized_op(sc, LOCK_HELD); return (rc); } static int sysctl_pause_settings(SYSCTL_HANDLER_ARGS) { struct port_info *pi = arg1; struct adapter *sc = pi->adapter; struct link_config *lc = &pi->link_cfg; int rc; if (req->newptr == NULL) { struct sbuf *sb; static char *bits = "\20\1PAUSE_RX\2PAUSE_TX"; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return(rc); sb = sbuf_new_for_sysctl(NULL, NULL, 128, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, "%b", lc->fc & (PAUSE_TX | PAUSE_RX), bits); rc = sbuf_finish(sb); sbuf_delete(sb); } else { char s[2]; int n; s[0] = '0' + (lc->requested_fc & (PAUSE_TX | PAUSE_RX)); s[1] = 0; rc = sysctl_handle_string(oidp, s, sizeof(s), req); if (rc != 0) return(rc); if (s[1] != 0) return (EINVAL); if (s[0] < '0' || s[0] > '9') return (EINVAL); /* not a number */ n = s[0] - '0'; if (n & ~(PAUSE_TX | PAUSE_RX)) return (EINVAL); /* some other bit is set too */ rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK, "t4PAUSE"); if (rc) return (rc); if ((lc->requested_fc & (PAUSE_TX | PAUSE_RX)) != n) { lc->requested_fc &= ~(PAUSE_TX | PAUSE_RX); lc->requested_fc |= n; rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc); if (rc == 0) { lc->fc = lc->requested_fc; } } end_synchronized_op(sc, 0); } return (rc); } static int sysctl_fec(SYSCTL_HANDLER_ARGS) { struct port_info *pi = arg1; struct adapter *sc = pi->adapter; struct link_config *lc = &pi->link_cfg; int rc; if (req->newptr == NULL) { struct sbuf *sb; static char *bits = "\20\1RS\2BASER_RS\3RESERVED"; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return(rc); sb = sbuf_new_for_sysctl(NULL, NULL, 128, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, "%b", lc->fec & M_FW_PORT_CAP_FEC, bits); rc = sbuf_finish(sb); sbuf_delete(sb); } else { char s[2]; int n; s[0] = '0' + (lc->requested_fec & M_FW_PORT_CAP_FEC); s[1] = 0; rc = sysctl_handle_string(oidp, s, sizeof(s), req); if (rc != 0) return(rc); if (s[1] != 0) return (EINVAL); if (s[0] < '0' || s[0] > '9') return (EINVAL); /* not a number */ n = s[0] - '0'; if (n & ~M_FW_PORT_CAP_FEC) return (EINVAL); /* some other bit is set too */ rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK, "t4fec"); if (rc) return (rc); if ((lc->requested_fec & M_FW_PORT_CAP_FEC) != n) { lc->requested_fec = n & G_FW_PORT_CAP_FEC(lc->supported); rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc); if (rc == 0) { lc->fec = lc->requested_fec; } } end_synchronized_op(sc, 0); } return (rc); } static int sysctl_autoneg(SYSCTL_HANDLER_ARGS) { struct port_info *pi = arg1; struct adapter *sc = pi->adapter; struct link_config *lc = &pi->link_cfg; int rc, val, old; if (lc->supported & FW_PORT_CAP_ANEG) val = lc->requested_aneg == AUTONEG_ENABLE ? 1 : 0; else val = -1; rc = sysctl_handle_int(oidp, &val, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if ((lc->supported & FW_PORT_CAP_ANEG) == 0) return (ENOTSUP); if (val == 0) val = AUTONEG_DISABLE; else if (val == 1) val = AUTONEG_ENABLE; else return (EINVAL); if (lc->requested_aneg == val) return (0); /* no change */ rc = begin_synchronized_op(sc, &pi->vi[0], SLEEP_OK | INTR_OK, "t4aneg"); if (rc) return (rc); old = lc->requested_aneg; lc->requested_aneg = val; rc = -t4_link_l1cfg(sc, sc->mbox, pi->tx_chan, lc); if (rc != 0) lc->requested_aneg = old; end_synchronized_op(sc, 0); return (rc); } static int sysctl_handle_t4_reg64(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; int reg = arg2; uint64_t val; val = t4_read_reg64(sc, reg); return (sysctl_handle_64(oidp, &val, 0, req)); } static int sysctl_temperature(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; int rc, t; uint32_t param, val; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4temp"); if (rc) return (rc); param = V_FW_PARAMS_MNEM(FW_PARAMS_MNEM_DEV) | V_FW_PARAMS_PARAM_X(FW_PARAMS_PARAM_DEV_DIAG) | V_FW_PARAMS_PARAM_Y(FW_PARAM_DEV_DIAG_TMP); rc = -t4_query_params(sc, sc->mbox, sc->pf, 0, 1, ¶m, &val); end_synchronized_op(sc, 0); if (rc) return (rc); /* unknown is returned as 0 but we display -1 in that case */ t = val == 0 ? -1 : val; rc = sysctl_handle_int(oidp, &t, 0, req); return (rc); } #ifdef SBUF_DRAIN static int sysctl_cctrl(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; uint16_t incr[NMTUS][NCCTRL_WIN]; static const char *dec_fac[] = { "0.5", "0.5625", "0.625", "0.6875", "0.75", "0.8125", "0.875", "0.9375" }; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); t4_read_cong_tbl(sc, incr); for (i = 0; i < NCCTRL_WIN; ++i) { sbuf_printf(sb, "%2d: %4u %4u %4u %4u %4u %4u %4u %4u\n", i, incr[0][i], incr[1][i], incr[2][i], incr[3][i], incr[4][i], incr[5][i], incr[6][i], incr[7][i]); sbuf_printf(sb, "%8u %4u %4u %4u %4u %4u %4u %4u %5u %s\n", incr[8][i], incr[9][i], incr[10][i], incr[11][i], incr[12][i], incr[13][i], incr[14][i], incr[15][i], sc->params.a_wnd[i], dec_fac[sc->params.b_wnd[i]]); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static const char *qname[CIM_NUM_IBQ + CIM_NUM_OBQ_T5] = { "TP0", "TP1", "ULP", "SGE0", "SGE1", "NC-SI", /* ibq's */ "ULP0", "ULP1", "ULP2", "ULP3", "SGE", "NC-SI", /* obq's */ "SGE0-RX", "SGE1-RX" /* additional obq's (T5 onwards) */ }; static int sysctl_cim_ibq_obq(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i, n, qid = arg2; uint32_t *buf, *p; char *qtype; u_int cim_num_obq = sc->chip_params->cim_num_obq; KASSERT(qid >= 0 && qid < CIM_NUM_IBQ + cim_num_obq, ("%s: bad qid %d\n", __func__, qid)); if (qid < CIM_NUM_IBQ) { /* inbound queue */ qtype = "IBQ"; n = 4 * CIM_IBQ_SIZE; buf = malloc(n * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); rc = t4_read_cim_ibq(sc, qid, buf, n); } else { /* outbound queue */ qtype = "OBQ"; qid -= CIM_NUM_IBQ; n = 4 * cim_num_obq * CIM_OBQ_SIZE; buf = malloc(n * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); rc = t4_read_cim_obq(sc, qid, buf, n); } if (rc < 0) { rc = -rc; goto done; } n = rc * sizeof(uint32_t); /* rc has # of words actually read */ rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) goto done; sb = sbuf_new_for_sysctl(NULL, NULL, PAGE_SIZE, req); if (sb == NULL) { rc = ENOMEM; goto done; } sbuf_printf(sb, "%s%d %s", qtype , qid, qname[arg2]); for (i = 0, p = buf; i < n; i += 16, p += 4) sbuf_printf(sb, "\n%#06x: %08x %08x %08x %08x", i, p[0], p[1], p[2], p[3]); rc = sbuf_finish(sb); sbuf_delete(sb); done: free(buf, M_CXGBE); return (rc); } static int sysctl_cim_la(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; u_int cfg; struct sbuf *sb; uint32_t *buf, *p; int rc; MPASS(chip_id(sc) <= CHELSIO_T5); rc = -t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg); if (rc != 0) return (rc); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(sc->params.cim_la_size * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); rc = -t4_cim_read_la(sc, buf, NULL); if (rc != 0) goto done; sbuf_printf(sb, "Status Data PC%s", cfg & F_UPDBGLACAPTPCONLY ? "" : " LS0Stat LS0Addr LS0Data"); for (p = buf; p <= &buf[sc->params.cim_la_size - 8]; p += 8) { if (cfg & F_UPDBGLACAPTPCONLY) { sbuf_printf(sb, "\n %02x %08x %08x", p[5] & 0xff, p[6], p[7]); sbuf_printf(sb, "\n %02x %02x%06x %02x%06x", (p[3] >> 8) & 0xff, p[3] & 0xff, p[4] >> 8, p[4] & 0xff, p[5] >> 8); sbuf_printf(sb, "\n %02x %x%07x %x%07x", (p[0] >> 4) & 0xff, p[0] & 0xf, p[1] >> 4, p[1] & 0xf, p[2] >> 4); } else { sbuf_printf(sb, "\n %02x %x%07x %x%07x %08x %08x " "%08x%08x%08x%08x", (p[0] >> 4) & 0xff, p[0] & 0xf, p[1] >> 4, p[1] & 0xf, p[2] >> 4, p[2] & 0xf, p[3], p[4], p[5], p[6], p[7]); } } rc = sbuf_finish(sb); sbuf_delete(sb); done: free(buf, M_CXGBE); return (rc); } static int sysctl_cim_la_t6(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; u_int cfg; struct sbuf *sb; uint32_t *buf, *p; int rc; MPASS(chip_id(sc) > CHELSIO_T5); rc = -t4_cim_read(sc, A_UP_UP_DBG_LA_CFG, 1, &cfg); if (rc != 0) return (rc); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(sc->params.cim_la_size * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); rc = -t4_cim_read_la(sc, buf, NULL); if (rc != 0) goto done; sbuf_printf(sb, "Status Inst Data PC%s", cfg & F_UPDBGLACAPTPCONLY ? "" : " LS0Stat LS0Addr LS0Data LS1Stat LS1Addr LS1Data"); for (p = buf; p <= &buf[sc->params.cim_la_size - 10]; p += 10) { if (cfg & F_UPDBGLACAPTPCONLY) { sbuf_printf(sb, "\n %02x %08x %08x %08x", p[3] & 0xff, p[2], p[1], p[0]); sbuf_printf(sb, "\n %02x %02x%06x %02x%06x %02x%06x", (p[6] >> 8) & 0xff, p[6] & 0xff, p[5] >> 8, p[5] & 0xff, p[4] >> 8, p[4] & 0xff, p[3] >> 8); sbuf_printf(sb, "\n %02x %04x%04x %04x%04x %04x%04x", (p[9] >> 16) & 0xff, p[9] & 0xffff, p[8] >> 16, p[8] & 0xffff, p[7] >> 16, p[7] & 0xffff, p[6] >> 16); } else { sbuf_printf(sb, "\n %02x %04x%04x %04x%04x %04x%04x " "%08x %08x %08x %08x %08x %08x", (p[9] >> 16) & 0xff, p[9] & 0xffff, p[8] >> 16, p[8] & 0xffff, p[7] >> 16, p[7] & 0xffff, p[6] >> 16, p[2], p[1], p[0], p[5], p[4], p[3]); } } rc = sbuf_finish(sb); sbuf_delete(sb); done: free(buf, M_CXGBE); return (rc); } static int sysctl_cim_ma_la(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; u_int i; struct sbuf *sb; uint32_t *buf, *p; int rc; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(2 * CIM_MALA_SIZE * 5 * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); t4_cim_read_ma_la(sc, buf, buf + 5 * CIM_MALA_SIZE); p = buf; for (i = 0; i < CIM_MALA_SIZE; i++, p += 5) { sbuf_printf(sb, "\n%02x%08x%08x%08x%08x", p[4], p[3], p[2], p[1], p[0]); } sbuf_printf(sb, "\n\nCnt ID Tag UE Data RDY VLD"); for (i = 0; i < CIM_MALA_SIZE; i++, p += 5) { sbuf_printf(sb, "\n%3u %2u %x %u %08x%08x %u %u", (p[2] >> 10) & 0xff, (p[2] >> 7) & 7, (p[2] >> 3) & 0xf, (p[2] >> 2) & 1, (p[1] >> 2) | ((p[2] & 3) << 30), (p[0] >> 2) | ((p[1] & 3) << 30), (p[0] >> 1) & 1, p[0] & 1); } rc = sbuf_finish(sb); sbuf_delete(sb); free(buf, M_CXGBE); return (rc); } static int sysctl_cim_pif_la(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; u_int i; struct sbuf *sb; uint32_t *buf, *p; int rc; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(2 * CIM_PIFLA_SIZE * 6 * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); t4_cim_read_pif_la(sc, buf, buf + 6 * CIM_PIFLA_SIZE, NULL, NULL); p = buf; sbuf_printf(sb, "Cntl ID DataBE Addr Data"); for (i = 0; i < CIM_PIFLA_SIZE; i++, p += 6) { sbuf_printf(sb, "\n %02x %02x %04x %08x %08x%08x%08x%08x", (p[5] >> 22) & 0xff, (p[5] >> 16) & 0x3f, p[5] & 0xffff, p[4], p[3], p[2], p[1], p[0]); } sbuf_printf(sb, "\n\nCntl ID Data"); for (i = 0; i < CIM_PIFLA_SIZE; i++, p += 6) { sbuf_printf(sb, "\n %02x %02x %08x%08x%08x%08x", (p[4] >> 6) & 0xff, p[4] & 0x3f, p[3], p[2], p[1], p[0]); } rc = sbuf_finish(sb); sbuf_delete(sb); free(buf, M_CXGBE); return (rc); } static int sysctl_cim_qcfg(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; uint16_t base[CIM_NUM_IBQ + CIM_NUM_OBQ_T5]; uint16_t size[CIM_NUM_IBQ + CIM_NUM_OBQ_T5]; uint16_t thres[CIM_NUM_IBQ]; uint32_t obq_wr[2 * CIM_NUM_OBQ_T5], *wr = obq_wr; uint32_t stat[4 * (CIM_NUM_IBQ + CIM_NUM_OBQ_T5)], *p = stat; u_int cim_num_obq, ibq_rdaddr, obq_rdaddr, nq; cim_num_obq = sc->chip_params->cim_num_obq; if (is_t4(sc)) { ibq_rdaddr = A_UP_IBQ_0_RDADDR; obq_rdaddr = A_UP_OBQ_0_REALADDR; } else { ibq_rdaddr = A_UP_IBQ_0_SHADOW_RDADDR; obq_rdaddr = A_UP_OBQ_0_SHADOW_REALADDR; } nq = CIM_NUM_IBQ + cim_num_obq; rc = -t4_cim_read(sc, ibq_rdaddr, 4 * nq, stat); if (rc == 0) rc = -t4_cim_read(sc, obq_rdaddr, 2 * cim_num_obq, obq_wr); if (rc != 0) return (rc); t4_read_cimq_cfg(sc, base, size, thres); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, PAGE_SIZE, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, " Queue Base Size Thres RdPtr WrPtr SOP EOP Avail"); for (i = 0; i < CIM_NUM_IBQ; i++, p += 4) sbuf_printf(sb, "\n%7s %5x %5u %5u %6x %4x %4u %4u %5u", qname[i], base[i], size[i], thres[i], G_IBQRDADDR(p[0]), G_IBQWRADDR(p[1]), G_QUESOPCNT(p[3]), G_QUEEOPCNT(p[3]), G_QUEREMFLITS(p[2]) * 16); for ( ; i < nq; i++, p += 4, wr += 2) sbuf_printf(sb, "\n%7s %5x %5u %12x %4x %4u %4u %5u", qname[i], base[i], size[i], G_QUERDADDR(p[0]) & 0x3fff, wr[0] - base[i], G_QUESOPCNT(p[3]), G_QUEEOPCNT(p[3]), G_QUEREMFLITS(p[2]) * 16); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_cpl_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_cpl_stats stats; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); mtx_lock(&sc->reg_lock); t4_tp_get_cpl_stats(sc, &stats, 0); mtx_unlock(&sc->reg_lock); if (sc->chip_params->nchan > 2) { sbuf_printf(sb, " channel 0 channel 1" " channel 2 channel 3"); sbuf_printf(sb, "\nCPL requests: %10u %10u %10u %10u", stats.req[0], stats.req[1], stats.req[2], stats.req[3]); sbuf_printf(sb, "\nCPL responses: %10u %10u %10u %10u", stats.rsp[0], stats.rsp[1], stats.rsp[2], stats.rsp[3]); } else { sbuf_printf(sb, " channel 0 channel 1"); sbuf_printf(sb, "\nCPL requests: %10u %10u", stats.req[0], stats.req[1]); sbuf_printf(sb, "\nCPL responses: %10u %10u", stats.rsp[0], stats.rsp[1]); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_ddp_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_usm_stats stats; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return(rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); t4_get_usm_stats(sc, &stats, 1); sbuf_printf(sb, "Frames: %u\n", stats.frames); sbuf_printf(sb, "Octets: %ju\n", stats.octets); sbuf_printf(sb, "Drops: %u", stats.drops); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static const char * const devlog_level_strings[] = { [FW_DEVLOG_LEVEL_EMERG] = "EMERG", [FW_DEVLOG_LEVEL_CRIT] = "CRIT", [FW_DEVLOG_LEVEL_ERR] = "ERR", [FW_DEVLOG_LEVEL_NOTICE] = "NOTICE", [FW_DEVLOG_LEVEL_INFO] = "INFO", [FW_DEVLOG_LEVEL_DEBUG] = "DEBUG" }; static const char * const devlog_facility_strings[] = { [FW_DEVLOG_FACILITY_CORE] = "CORE", [FW_DEVLOG_FACILITY_CF] = "CF", [FW_DEVLOG_FACILITY_SCHED] = "SCHED", [FW_DEVLOG_FACILITY_TIMER] = "TIMER", [FW_DEVLOG_FACILITY_RES] = "RES", [FW_DEVLOG_FACILITY_HW] = "HW", [FW_DEVLOG_FACILITY_FLR] = "FLR", [FW_DEVLOG_FACILITY_DMAQ] = "DMAQ", [FW_DEVLOG_FACILITY_PHY] = "PHY", [FW_DEVLOG_FACILITY_MAC] = "MAC", [FW_DEVLOG_FACILITY_PORT] = "PORT", [FW_DEVLOG_FACILITY_VI] = "VI", [FW_DEVLOG_FACILITY_FILTER] = "FILTER", [FW_DEVLOG_FACILITY_ACL] = "ACL", [FW_DEVLOG_FACILITY_TM] = "TM", [FW_DEVLOG_FACILITY_QFC] = "QFC", [FW_DEVLOG_FACILITY_DCB] = "DCB", [FW_DEVLOG_FACILITY_ETH] = "ETH", [FW_DEVLOG_FACILITY_OFLD] = "OFLD", [FW_DEVLOG_FACILITY_RI] = "RI", [FW_DEVLOG_FACILITY_ISCSI] = "ISCSI", [FW_DEVLOG_FACILITY_FCOE] = "FCOE", [FW_DEVLOG_FACILITY_FOISCSI] = "FOISCSI", [FW_DEVLOG_FACILITY_FOFCOE] = "FOFCOE", [FW_DEVLOG_FACILITY_CHNET] = "CHNET", }; static int sysctl_devlog(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct devlog_params *dparams = &sc->params.devlog; struct fw_devlog_e *buf, *e; int i, j, rc, nentries, first = 0; struct sbuf *sb; uint64_t ftstamp = UINT64_MAX; if (dparams->addr == 0) return (ENXIO); buf = malloc(dparams->size, M_CXGBE, M_NOWAIT); if (buf == NULL) return (ENOMEM); rc = read_via_memwin(sc, 1, dparams->addr, (void *)buf, dparams->size); if (rc != 0) goto done; nentries = dparams->size / sizeof(struct fw_devlog_e); for (i = 0; i < nentries; i++) { e = &buf[i]; if (e->timestamp == 0) break; /* end */ e->timestamp = be64toh(e->timestamp); e->seqno = be32toh(e->seqno); for (j = 0; j < 8; j++) e->params[j] = be32toh(e->params[j]); if (e->timestamp < ftstamp) { ftstamp = e->timestamp; first = i; } } if (buf[first].timestamp == 0) goto done; /* nothing in the log */ rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) goto done; sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) { rc = ENOMEM; goto done; } sbuf_printf(sb, "%10s %15s %8s %8s %s\n", "Seq#", "Tstamp", "Level", "Facility", "Message"); i = first; do { e = &buf[i]; if (e->timestamp == 0) break; /* end */ sbuf_printf(sb, "%10d %15ju %8s %8s ", e->seqno, e->timestamp, (e->level < nitems(devlog_level_strings) ? devlog_level_strings[e->level] : "UNKNOWN"), (e->facility < nitems(devlog_facility_strings) ? devlog_facility_strings[e->facility] : "UNKNOWN")); sbuf_printf(sb, e->fmt, e->params[0], e->params[1], e->params[2], e->params[3], e->params[4], e->params[5], e->params[6], e->params[7]); if (++i == nentries) i = 0; } while (i != first); rc = sbuf_finish(sb); sbuf_delete(sb); done: free(buf, M_CXGBE); return (rc); } static int sysctl_fcoe_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_fcoe_stats stats[MAX_NCHAN]; int i, nchan = sc->chip_params->nchan; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); for (i = 0; i < nchan; i++) t4_get_fcoe_stats(sc, i, &stats[i], 1); if (nchan > 2) { sbuf_printf(sb, " channel 0 channel 1" " channel 2 channel 3"); sbuf_printf(sb, "\noctetsDDP: %16ju %16ju %16ju %16ju", stats[0].octets_ddp, stats[1].octets_ddp, stats[2].octets_ddp, stats[3].octets_ddp); sbuf_printf(sb, "\nframesDDP: %16u %16u %16u %16u", stats[0].frames_ddp, stats[1].frames_ddp, stats[2].frames_ddp, stats[3].frames_ddp); sbuf_printf(sb, "\nframesDrop: %16u %16u %16u %16u", stats[0].frames_drop, stats[1].frames_drop, stats[2].frames_drop, stats[3].frames_drop); } else { sbuf_printf(sb, " channel 0 channel 1"); sbuf_printf(sb, "\noctetsDDP: %16ju %16ju", stats[0].octets_ddp, stats[1].octets_ddp); sbuf_printf(sb, "\nframesDDP: %16u %16u", stats[0].frames_ddp, stats[1].frames_ddp); sbuf_printf(sb, "\nframesDrop: %16u %16u", stats[0].frames_drop, stats[1].frames_drop); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_hw_sched(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; unsigned int map, kbps, ipg, mode; unsigned int pace_tab[NTX_SCHED]; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); map = t4_read_reg(sc, A_TP_TX_MOD_QUEUE_REQ_MAP); mode = G_TIMERMODE(t4_read_reg(sc, A_TP_MOD_CONFIG)); t4_read_pace_tbl(sc, pace_tab); sbuf_printf(sb, "Scheduler Mode Channel Rate (Kbps) " "Class IPG (0.1 ns) Flow IPG (us)"); for (i = 0; i < NTX_SCHED; ++i, map >>= 2) { t4_get_tx_sched(sc, i, &kbps, &ipg, 1); sbuf_printf(sb, "\n %u %-5s %u ", i, (mode & (1 << i)) ? "flow" : "class", map & 3); if (kbps) sbuf_printf(sb, "%9u ", kbps); else sbuf_printf(sb, " disabled "); if (ipg) sbuf_printf(sb, "%13u ", ipg); else sbuf_printf(sb, " disabled "); if (pace_tab[i]) sbuf_printf(sb, "%10u", pace_tab[i]); else sbuf_printf(sb, " disabled"); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_lb_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i, j; uint64_t *p0, *p1; struct lb_port_stats s[2]; static const char *stat_name[] = { "OctetsOK:", "FramesOK:", "BcastFrames:", "McastFrames:", "UcastFrames:", "ErrorFrames:", "Frames64:", "Frames65To127:", "Frames128To255:", "Frames256To511:", "Frames512To1023:", "Frames1024To1518:", "Frames1519ToMax:", "FramesDropped:", "BG0FramesDropped:", "BG1FramesDropped:", "BG2FramesDropped:", "BG3FramesDropped:", "BG0FramesTrunc:", "BG1FramesTrunc:", "BG2FramesTrunc:", "BG3FramesTrunc:" }; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); memset(s, 0, sizeof(s)); for (i = 0; i < sc->chip_params->nchan; i += 2) { t4_get_lb_stats(sc, i, &s[0]); t4_get_lb_stats(sc, i + 1, &s[1]); p0 = &s[0].octets; p1 = &s[1].octets; sbuf_printf(sb, "%s Loopback %u" " Loopback %u", i == 0 ? "" : "\n", i, i + 1); for (j = 0; j < nitems(stat_name); j++) sbuf_printf(sb, "\n%-17s %20ju %20ju", stat_name[j], *p0++, *p1++); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_linkdnrc(SYSCTL_HANDLER_ARGS) { int rc = 0; struct port_info *pi = arg1; struct link_config *lc = &pi->link_cfg; struct sbuf *sb; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return(rc); sb = sbuf_new_for_sysctl(NULL, NULL, 64, req); if (sb == NULL) return (ENOMEM); if (lc->link_ok || lc->link_down_rc == 255) sbuf_printf(sb, "n/a"); else sbuf_printf(sb, "%s", t4_link_down_rc_str(lc->link_down_rc)); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } struct mem_desc { unsigned int base; unsigned int limit; unsigned int idx; }; static int mem_desc_cmp(const void *a, const void *b) { return ((const struct mem_desc *)a)->base - ((const struct mem_desc *)b)->base; } static void mem_region_show(struct sbuf *sb, const char *name, unsigned int from, unsigned int to) { unsigned int size; if (from == to) return; size = to - from + 1; if (size == 0) return; /* XXX: need humanize_number(3) in libkern for a more readable 'size' */ sbuf_printf(sb, "%-15s %#x-%#x [%u]\n", name, from, to, size); } static int sysctl_meminfo(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i, n; uint32_t lo, hi, used, alloc; static const char *memory[] = {"EDC0:", "EDC1:", "MC:", "MC0:", "MC1:"}; static const char *region[] = { "DBQ contexts:", "IMSG contexts:", "FLM cache:", "TCBs:", "Pstructs:", "Timers:", "Rx FL:", "Tx FL:", "Pstruct FL:", "Tx payload:", "Rx payload:", "LE hash:", "iSCSI region:", "TDDP region:", "TPT region:", "STAG region:", "RQ region:", "RQUDP region:", "PBL region:", "TXPBL region:", "DBVFIFO region:", "ULPRX state:", "ULPTX state:", "On-chip queues:" }; struct mem_desc avail[4]; struct mem_desc mem[nitems(region) + 3]; /* up to 3 holes */ struct mem_desc *md = mem; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); for (i = 0; i < nitems(mem); i++) { mem[i].limit = 0; mem[i].idx = i; } /* Find and sort the populated memory ranges */ i = 0; lo = t4_read_reg(sc, A_MA_TARGET_MEM_ENABLE); if (lo & F_EDRAM0_ENABLE) { hi = t4_read_reg(sc, A_MA_EDRAM0_BAR); avail[i].base = G_EDRAM0_BASE(hi) << 20; avail[i].limit = avail[i].base + (G_EDRAM0_SIZE(hi) << 20); avail[i].idx = 0; i++; } if (lo & F_EDRAM1_ENABLE) { hi = t4_read_reg(sc, A_MA_EDRAM1_BAR); avail[i].base = G_EDRAM1_BASE(hi) << 20; avail[i].limit = avail[i].base + (G_EDRAM1_SIZE(hi) << 20); avail[i].idx = 1; i++; } if (lo & F_EXT_MEM_ENABLE) { hi = t4_read_reg(sc, A_MA_EXT_MEMORY_BAR); avail[i].base = G_EXT_MEM_BASE(hi) << 20; avail[i].limit = avail[i].base + (G_EXT_MEM_SIZE(hi) << 20); avail[i].idx = is_t5(sc) ? 3 : 2; /* Call it MC0 for T5 */ i++; } if (is_t5(sc) && lo & F_EXT_MEM1_ENABLE) { hi = t4_read_reg(sc, A_MA_EXT_MEMORY1_BAR); avail[i].base = G_EXT_MEM1_BASE(hi) << 20; avail[i].limit = avail[i].base + (G_EXT_MEM1_SIZE(hi) << 20); avail[i].idx = 4; i++; } if (!i) /* no memory available */ return 0; qsort(avail, i, sizeof(struct mem_desc), mem_desc_cmp); (md++)->base = t4_read_reg(sc, A_SGE_DBQ_CTXT_BADDR); (md++)->base = t4_read_reg(sc, A_SGE_IMSG_CTXT_BADDR); (md++)->base = t4_read_reg(sc, A_SGE_FLM_CACHE_BADDR); (md++)->base = t4_read_reg(sc, A_TP_CMM_TCB_BASE); (md++)->base = t4_read_reg(sc, A_TP_CMM_MM_BASE); (md++)->base = t4_read_reg(sc, A_TP_CMM_TIMER_BASE); (md++)->base = t4_read_reg(sc, A_TP_CMM_MM_RX_FLST_BASE); (md++)->base = t4_read_reg(sc, A_TP_CMM_MM_TX_FLST_BASE); (md++)->base = t4_read_reg(sc, A_TP_CMM_MM_PS_FLST_BASE); /* the next few have explicit upper bounds */ md->base = t4_read_reg(sc, A_TP_PMM_TX_BASE); md->limit = md->base - 1 + t4_read_reg(sc, A_TP_PMM_TX_PAGE_SIZE) * G_PMTXMAXPAGE(t4_read_reg(sc, A_TP_PMM_TX_MAX_PAGE)); md++; md->base = t4_read_reg(sc, A_TP_PMM_RX_BASE); md->limit = md->base - 1 + t4_read_reg(sc, A_TP_PMM_RX_PAGE_SIZE) * G_PMRXMAXPAGE(t4_read_reg(sc, A_TP_PMM_RX_MAX_PAGE)); md++; if (t4_read_reg(sc, A_LE_DB_CONFIG) & F_HASHEN) { if (chip_id(sc) <= CHELSIO_T5) md->base = t4_read_reg(sc, A_LE_DB_HASH_TID_BASE); else md->base = t4_read_reg(sc, A_LE_DB_HASH_TBL_BASE_ADDR); md->limit = 0; } else { md->base = 0; md->idx = nitems(region); /* hide it */ } md++; #define ulp_region(reg) \ md->base = t4_read_reg(sc, A_ULP_ ## reg ## _LLIMIT);\ (md++)->limit = t4_read_reg(sc, A_ULP_ ## reg ## _ULIMIT) ulp_region(RX_ISCSI); ulp_region(RX_TDDP); ulp_region(TX_TPT); ulp_region(RX_STAG); ulp_region(RX_RQ); ulp_region(RX_RQUDP); ulp_region(RX_PBL); ulp_region(TX_PBL); #undef ulp_region md->base = 0; md->idx = nitems(region); if (!is_t4(sc)) { uint32_t size = 0; uint32_t sge_ctrl = t4_read_reg(sc, A_SGE_CONTROL2); uint32_t fifo_size = t4_read_reg(sc, A_SGE_DBVFIFO_SIZE); if (is_t5(sc)) { if (sge_ctrl & F_VFIFO_ENABLE) size = G_DBVFIFO_SIZE(fifo_size); } else size = G_T6_DBVFIFO_SIZE(fifo_size); if (size) { md->base = G_BASEADDR(t4_read_reg(sc, A_SGE_DBVFIFO_BADDR)); md->limit = md->base + (size << 2) - 1; } } md++; md->base = t4_read_reg(sc, A_ULP_RX_CTX_BASE); md->limit = 0; md++; md->base = t4_read_reg(sc, A_ULP_TX_ERR_TABLE_BASE); md->limit = 0; md++; md->base = sc->vres.ocq.start; if (sc->vres.ocq.size) md->limit = md->base + sc->vres.ocq.size - 1; else md->idx = nitems(region); /* hide it */ md++; /* add any address-space holes, there can be up to 3 */ for (n = 0; n < i - 1; n++) if (avail[n].limit < avail[n + 1].base) (md++)->base = avail[n].limit; if (avail[n].limit) (md++)->base = avail[n].limit; n = md - mem; qsort(mem, n, sizeof(struct mem_desc), mem_desc_cmp); for (lo = 0; lo < i; lo++) mem_region_show(sb, memory[avail[lo].idx], avail[lo].base, avail[lo].limit - 1); sbuf_printf(sb, "\n"); for (i = 0; i < n; i++) { if (mem[i].idx >= nitems(region)) continue; /* skip holes */ if (!mem[i].limit) mem[i].limit = i < n - 1 ? mem[i + 1].base - 1 : ~0; mem_region_show(sb, region[mem[i].idx], mem[i].base, mem[i].limit); } sbuf_printf(sb, "\n"); lo = t4_read_reg(sc, A_CIM_SDRAM_BASE_ADDR); hi = t4_read_reg(sc, A_CIM_SDRAM_ADDR_SIZE) + lo - 1; mem_region_show(sb, "uP RAM:", lo, hi); lo = t4_read_reg(sc, A_CIM_EXTMEM2_BASE_ADDR); hi = t4_read_reg(sc, A_CIM_EXTMEM2_ADDR_SIZE) + lo - 1; mem_region_show(sb, "uP Extmem2:", lo, hi); lo = t4_read_reg(sc, A_TP_PMM_RX_MAX_PAGE); sbuf_printf(sb, "\n%u Rx pages of size %uKiB for %u channels\n", G_PMRXMAXPAGE(lo), t4_read_reg(sc, A_TP_PMM_RX_PAGE_SIZE) >> 10, (lo & F_PMRXNUMCHN) ? 2 : 1); lo = t4_read_reg(sc, A_TP_PMM_TX_MAX_PAGE); hi = t4_read_reg(sc, A_TP_PMM_TX_PAGE_SIZE); sbuf_printf(sb, "%u Tx pages of size %u%ciB for %u channels\n", G_PMTXMAXPAGE(lo), hi >= (1 << 20) ? (hi >> 20) : (hi >> 10), hi >= (1 << 20) ? 'M' : 'K', 1 << G_PMTXNUMCHN(lo)); sbuf_printf(sb, "%u p-structs\n", t4_read_reg(sc, A_TP_CMM_MM_MAX_PSTRUCT)); for (i = 0; i < 4; i++) { if (chip_id(sc) > CHELSIO_T5) lo = t4_read_reg(sc, A_MPS_RX_MAC_BG_PG_CNT0 + i * 4); else lo = t4_read_reg(sc, A_MPS_RX_PG_RSV0 + i * 4); if (is_t5(sc)) { used = G_T5_USED(lo); alloc = G_T5_ALLOC(lo); } else { used = G_USED(lo); alloc = G_ALLOC(lo); } /* For T6 these are MAC buffer groups */ sbuf_printf(sb, "\nPort %d using %u pages out of %u allocated", i, used, alloc); } for (i = 0; i < sc->chip_params->nchan; i++) { if (chip_id(sc) > CHELSIO_T5) lo = t4_read_reg(sc, A_MPS_RX_LPBK_BG_PG_CNT0 + i * 4); else lo = t4_read_reg(sc, A_MPS_RX_PG_RSV4 + i * 4); if (is_t5(sc)) { used = G_T5_USED(lo); alloc = G_T5_ALLOC(lo); } else { used = G_USED(lo); alloc = G_ALLOC(lo); } /* For T6 these are MAC buffer groups */ sbuf_printf(sb, "\nLoopback %d using %u pages out of %u allocated", i, used, alloc); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static inline void tcamxy2valmask(uint64_t x, uint64_t y, uint8_t *addr, uint64_t *mask) { *mask = x | y; y = htobe64(y); memcpy(addr, (char *)&y + 2, ETHER_ADDR_LEN); } static int sysctl_mps_tcam(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; MPASS(chip_id(sc) <= CHELSIO_T5); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, "Idx Ethernet address Mask Vld Ports PF" " VF Replication P0 P1 P2 P3 ML"); for (i = 0; i < sc->chip_params->mps_tcam_size; i++) { uint64_t tcamx, tcamy, mask; uint32_t cls_lo, cls_hi; uint8_t addr[ETHER_ADDR_LEN]; tcamy = t4_read_reg64(sc, MPS_CLS_TCAM_Y_L(i)); tcamx = t4_read_reg64(sc, MPS_CLS_TCAM_X_L(i)); if (tcamx & tcamy) continue; tcamxy2valmask(tcamx, tcamy, addr, &mask); cls_lo = t4_read_reg(sc, MPS_CLS_SRAM_L(i)); cls_hi = t4_read_reg(sc, MPS_CLS_SRAM_H(i)); sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x %012jx" " %c %#x%4u%4d", i, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], (uintmax_t)mask, (cls_lo & F_SRAM_VLD) ? 'Y' : 'N', G_PORTMAP(cls_hi), G_PF(cls_lo), (cls_lo & F_VF_VALID) ? G_VF(cls_lo) : -1); if (cls_lo & F_REPLICATE) { struct fw_ldst_cmd ldst_cmd; memset(&ldst_cmd, 0, sizeof(ldst_cmd)); ldst_cmd.op_to_addrspace = htobe32(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MPS)); ldst_cmd.cycles_to_len16 = htobe32(FW_LEN16(ldst_cmd)); ldst_cmd.u.mps.rplc.fid_idx = htobe16(V_FW_LDST_CMD_FID(FW_LDST_MPS_RPLC) | V_FW_LDST_CMD_IDX(i)); rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4mps"); if (rc) break; rc = -t4_wr_mbox(sc, sc->mbox, &ldst_cmd, sizeof(ldst_cmd), &ldst_cmd); end_synchronized_op(sc, 0); if (rc != 0) { sbuf_printf(sb, "%36d", rc); rc = 0; } else { sbuf_printf(sb, " %08x %08x %08x %08x", be32toh(ldst_cmd.u.mps.rplc.rplc127_96), be32toh(ldst_cmd.u.mps.rplc.rplc95_64), be32toh(ldst_cmd.u.mps.rplc.rplc63_32), be32toh(ldst_cmd.u.mps.rplc.rplc31_0)); } } else sbuf_printf(sb, "%36s", ""); sbuf_printf(sb, "%4u%3u%3u%3u %#3x", G_SRAM_PRIO0(cls_lo), G_SRAM_PRIO1(cls_lo), G_SRAM_PRIO2(cls_lo), G_SRAM_PRIO3(cls_lo), (cls_lo >> S_MULTILISTEN0) & 0xf); } if (rc) (void) sbuf_finish(sb); else rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_mps_tcam_t6(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; MPASS(chip_id(sc) > CHELSIO_T5); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); sbuf_printf(sb, "Idx Ethernet address Mask VNI Mask" " IVLAN Vld DIP_Hit Lookup Port Vld Ports PF VF" " Replication" " P0 P1 P2 P3 ML\n"); for (i = 0; i < sc->chip_params->mps_tcam_size; i++) { uint8_t dip_hit, vlan_vld, lookup_type, port_num; uint16_t ivlan; uint64_t tcamx, tcamy, val, mask; uint32_t cls_lo, cls_hi, ctl, data2, vnix, vniy; uint8_t addr[ETHER_ADDR_LEN]; ctl = V_CTLREQID(1) | V_CTLCMDTYPE(0) | V_CTLXYBITSEL(0); if (i < 256) ctl |= V_CTLTCAMINDEX(i) | V_CTLTCAMSEL(0); else ctl |= V_CTLTCAMINDEX(i - 256) | V_CTLTCAMSEL(1); t4_write_reg(sc, A_MPS_CLS_TCAM_DATA2_CTL, ctl); val = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA1_REQ_ID1); tcamy = G_DMACH(val) << 32; tcamy |= t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA0_REQ_ID1); data2 = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA2_REQ_ID1); lookup_type = G_DATALKPTYPE(data2); port_num = G_DATAPORTNUM(data2); if (lookup_type && lookup_type != M_DATALKPTYPE) { /* Inner header VNI */ vniy = ((data2 & F_DATAVIDH2) << 23) | (G_DATAVIDH1(data2) << 16) | G_VIDL(val); dip_hit = data2 & F_DATADIPHIT; vlan_vld = 0; } else { vniy = 0; dip_hit = 0; vlan_vld = data2 & F_DATAVIDH2; ivlan = G_VIDL(val); } ctl |= V_CTLXYBITSEL(1); t4_write_reg(sc, A_MPS_CLS_TCAM_DATA2_CTL, ctl); val = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA1_REQ_ID1); tcamx = G_DMACH(val) << 32; tcamx |= t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA0_REQ_ID1); data2 = t4_read_reg(sc, A_MPS_CLS_TCAM_RDATA2_REQ_ID1); if (lookup_type && lookup_type != M_DATALKPTYPE) { /* Inner header VNI mask */ vnix = ((data2 & F_DATAVIDH2) << 23) | (G_DATAVIDH1(data2) << 16) | G_VIDL(val); } else vnix = 0; if (tcamx & tcamy) continue; tcamxy2valmask(tcamx, tcamy, addr, &mask); cls_lo = t4_read_reg(sc, MPS_CLS_SRAM_L(i)); cls_hi = t4_read_reg(sc, MPS_CLS_SRAM_H(i)); if (lookup_type && lookup_type != M_DATALKPTYPE) { sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x " "%012jx %06x %06x - - %3c" " 'I' %4x %3c %#x%4u%4d", i, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], (uintmax_t)mask, vniy, vnix, dip_hit ? 'Y' : 'N', port_num, cls_lo & F_T6_SRAM_VLD ? 'Y' : 'N', G_PORTMAP(cls_hi), G_T6_PF(cls_lo), cls_lo & F_T6_VF_VALID ? G_T6_VF(cls_lo) : -1); } else { sbuf_printf(sb, "\n%3u %02x:%02x:%02x:%02x:%02x:%02x " "%012jx - - ", i, addr[0], addr[1], addr[2], addr[3], addr[4], addr[5], (uintmax_t)mask); if (vlan_vld) sbuf_printf(sb, "%4u Y ", ivlan); else sbuf_printf(sb, " - N "); sbuf_printf(sb, "- %3c %4x %3c %#x%4u%4d", lookup_type ? 'I' : 'O', port_num, cls_lo & F_T6_SRAM_VLD ? 'Y' : 'N', G_PORTMAP(cls_hi), G_T6_PF(cls_lo), cls_lo & F_T6_VF_VALID ? G_T6_VF(cls_lo) : -1); } if (cls_lo & F_T6_REPLICATE) { struct fw_ldst_cmd ldst_cmd; memset(&ldst_cmd, 0, sizeof(ldst_cmd)); ldst_cmd.op_to_addrspace = htobe32(V_FW_CMD_OP(FW_LDST_CMD) | F_FW_CMD_REQUEST | F_FW_CMD_READ | V_FW_LDST_CMD_ADDRSPACE(FW_LDST_ADDRSPC_MPS)); ldst_cmd.cycles_to_len16 = htobe32(FW_LEN16(ldst_cmd)); ldst_cmd.u.mps.rplc.fid_idx = htobe16(V_FW_LDST_CMD_FID(FW_LDST_MPS_RPLC) | V_FW_LDST_CMD_IDX(i)); rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t6mps"); if (rc) break; rc = -t4_wr_mbox(sc, sc->mbox, &ldst_cmd, sizeof(ldst_cmd), &ldst_cmd); end_synchronized_op(sc, 0); if (rc != 0) { sbuf_printf(sb, "%72d", rc); rc = 0; } else { sbuf_printf(sb, " %08x %08x %08x %08x" " %08x %08x %08x %08x", be32toh(ldst_cmd.u.mps.rplc.rplc255_224), be32toh(ldst_cmd.u.mps.rplc.rplc223_192), be32toh(ldst_cmd.u.mps.rplc.rplc191_160), be32toh(ldst_cmd.u.mps.rplc.rplc159_128), be32toh(ldst_cmd.u.mps.rplc.rplc127_96), be32toh(ldst_cmd.u.mps.rplc.rplc95_64), be32toh(ldst_cmd.u.mps.rplc.rplc63_32), be32toh(ldst_cmd.u.mps.rplc.rplc31_0)); } } else sbuf_printf(sb, "%72s", ""); sbuf_printf(sb, "%4u%3u%3u%3u %#x", G_T6_SRAM_PRIO0(cls_lo), G_T6_SRAM_PRIO1(cls_lo), G_T6_SRAM_PRIO2(cls_lo), G_T6_SRAM_PRIO3(cls_lo), (cls_lo >> S_T6_MULTILISTEN0) & 0xf); } if (rc) (void) sbuf_finish(sb); else rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_path_mtus(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; uint16_t mtus[NMTUS]; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); t4_read_mtu_tbl(sc, mtus, NULL); sbuf_printf(sb, "%u %u %u %u %u %u %u %u %u %u %u %u %u %u %u %u", mtus[0], mtus[1], mtus[2], mtus[3], mtus[4], mtus[5], mtus[6], mtus[7], mtus[8], mtus[9], mtus[10], mtus[11], mtus[12], mtus[13], mtus[14], mtus[15]); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_pm_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, i; uint32_t tx_cnt[MAX_PM_NSTATS], rx_cnt[MAX_PM_NSTATS]; uint64_t tx_cyc[MAX_PM_NSTATS], rx_cyc[MAX_PM_NSTATS]; static const char *tx_stats[MAX_PM_NSTATS] = { "Read:", "Write bypass:", "Write mem:", "Bypass + mem:", "Tx FIFO wait", NULL, "Tx latency" }; static const char *rx_stats[MAX_PM_NSTATS] = { "Read:", "Write bypass:", "Write mem:", "Flush:", "Rx FIFO wait", NULL, "Rx latency" }; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); t4_pmtx_get_stats(sc, tx_cnt, tx_cyc); t4_pmrx_get_stats(sc, rx_cnt, rx_cyc); sbuf_printf(sb, " Tx pcmds Tx bytes"); for (i = 0; i < 4; i++) { sbuf_printf(sb, "\n%-13s %10u %20ju", tx_stats[i], tx_cnt[i], tx_cyc[i]); } sbuf_printf(sb, "\n Rx pcmds Rx bytes"); for (i = 0; i < 4; i++) { sbuf_printf(sb, "\n%-13s %10u %20ju", rx_stats[i], rx_cnt[i], rx_cyc[i]); } if (chip_id(sc) > CHELSIO_T5) { sbuf_printf(sb, "\n Total wait Total occupancy"); sbuf_printf(sb, "\n%-13s %10u %20ju", tx_stats[i], tx_cnt[i], tx_cyc[i]); sbuf_printf(sb, "\n%-13s %10u %20ju", rx_stats[i], rx_cnt[i], rx_cyc[i]); i += 2; MPASS(i < nitems(tx_stats)); sbuf_printf(sb, "\n Reads Total wait"); sbuf_printf(sb, "\n%-13s %10u %20ju", tx_stats[i], tx_cnt[i], tx_cyc[i]); sbuf_printf(sb, "\n%-13s %10u %20ju", rx_stats[i], rx_cnt[i], rx_cyc[i]); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_rdma_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_rdma_stats stats; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); mtx_lock(&sc->reg_lock); t4_tp_get_rdma_stats(sc, &stats, 0); mtx_unlock(&sc->reg_lock); sbuf_printf(sb, "NoRQEModDefferals: %u\n", stats.rqe_dfr_mod); sbuf_printf(sb, "NoRQEPktDefferals: %u", stats.rqe_dfr_pkt); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_tcp_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_tcp_stats v4, v6; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); mtx_lock(&sc->reg_lock); t4_tp_get_tcp_stats(sc, &v4, &v6, 0); mtx_unlock(&sc->reg_lock); sbuf_printf(sb, " IP IPv6\n"); sbuf_printf(sb, "OutRsts: %20u %20u\n", v4.tcp_out_rsts, v6.tcp_out_rsts); sbuf_printf(sb, "InSegs: %20ju %20ju\n", v4.tcp_in_segs, v6.tcp_in_segs); sbuf_printf(sb, "OutSegs: %20ju %20ju\n", v4.tcp_out_segs, v6.tcp_out_segs); sbuf_printf(sb, "RetransSegs: %20ju %20ju", v4.tcp_retrans_segs, v6.tcp_retrans_segs); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_tids(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tid_info *t = &sc->tids; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); if (t->natids) { sbuf_printf(sb, "ATID range: 0-%u, in use: %u\n", t->natids - 1, t->atids_in_use); } if (t->ntids) { sbuf_printf(sb, "TID range: "); if (t4_read_reg(sc, A_LE_DB_CONFIG) & F_HASHEN) { uint32_t b, hb; if (chip_id(sc) <= CHELSIO_T5) { b = t4_read_reg(sc, A_LE_DB_SERVER_INDEX) / 4; hb = t4_read_reg(sc, A_LE_DB_TID_HASHBASE) / 4; } else { b = t4_read_reg(sc, A_LE_DB_SRVR_START_INDEX); hb = t4_read_reg(sc, A_T6_LE_DB_HASH_TID_BASE); } if (b) sbuf_printf(sb, "0-%u, ", b - 1); sbuf_printf(sb, "%u-%u", hb, t->ntids - 1); } else sbuf_printf(sb, "0-%u", t->ntids - 1); sbuf_printf(sb, ", in use: %u\n", atomic_load_acq_int(&t->tids_in_use)); } if (t->nstids) { sbuf_printf(sb, "STID range: %u-%u, in use: %u\n", t->stid_base, t->stid_base + t->nstids - 1, t->stids_in_use); } if (t->nftids) { sbuf_printf(sb, "FTID range: %u-%u\n", t->ftid_base, t->ftid_base + t->nftids - 1); } if (t->netids) { sbuf_printf(sb, "ETID range: %u-%u\n", t->etid_base, t->etid_base + t->netids - 1); } sbuf_printf(sb, "HW TID usage: %u IP users, %u IPv6 users", t4_read_reg(sc, A_LE_DB_ACT_CNT_IPV4), t4_read_reg(sc, A_LE_DB_ACT_CNT_IPV6)); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_tp_err_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; struct tp_err_stats stats; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); mtx_lock(&sc->reg_lock); t4_tp_get_err_stats(sc, &stats, 0); mtx_unlock(&sc->reg_lock); if (sc->chip_params->nchan > 2) { sbuf_printf(sb, " channel 0 channel 1" " channel 2 channel 3\n"); sbuf_printf(sb, "macInErrs: %10u %10u %10u %10u\n", stats.mac_in_errs[0], stats.mac_in_errs[1], stats.mac_in_errs[2], stats.mac_in_errs[3]); sbuf_printf(sb, "hdrInErrs: %10u %10u %10u %10u\n", stats.hdr_in_errs[0], stats.hdr_in_errs[1], stats.hdr_in_errs[2], stats.hdr_in_errs[3]); sbuf_printf(sb, "tcpInErrs: %10u %10u %10u %10u\n", stats.tcp_in_errs[0], stats.tcp_in_errs[1], stats.tcp_in_errs[2], stats.tcp_in_errs[3]); sbuf_printf(sb, "tcp6InErrs: %10u %10u %10u %10u\n", stats.tcp6_in_errs[0], stats.tcp6_in_errs[1], stats.tcp6_in_errs[2], stats.tcp6_in_errs[3]); sbuf_printf(sb, "tnlCongDrops: %10u %10u %10u %10u\n", stats.tnl_cong_drops[0], stats.tnl_cong_drops[1], stats.tnl_cong_drops[2], stats.tnl_cong_drops[3]); sbuf_printf(sb, "tnlTxDrops: %10u %10u %10u %10u\n", stats.tnl_tx_drops[0], stats.tnl_tx_drops[1], stats.tnl_tx_drops[2], stats.tnl_tx_drops[3]); sbuf_printf(sb, "ofldVlanDrops: %10u %10u %10u %10u\n", stats.ofld_vlan_drops[0], stats.ofld_vlan_drops[1], stats.ofld_vlan_drops[2], stats.ofld_vlan_drops[3]); sbuf_printf(sb, "ofldChanDrops: %10u %10u %10u %10u\n\n", stats.ofld_chan_drops[0], stats.ofld_chan_drops[1], stats.ofld_chan_drops[2], stats.ofld_chan_drops[3]); } else { sbuf_printf(sb, " channel 0 channel 1\n"); sbuf_printf(sb, "macInErrs: %10u %10u\n", stats.mac_in_errs[0], stats.mac_in_errs[1]); sbuf_printf(sb, "hdrInErrs: %10u %10u\n", stats.hdr_in_errs[0], stats.hdr_in_errs[1]); sbuf_printf(sb, "tcpInErrs: %10u %10u\n", stats.tcp_in_errs[0], stats.tcp_in_errs[1]); sbuf_printf(sb, "tcp6InErrs: %10u %10u\n", stats.tcp6_in_errs[0], stats.tcp6_in_errs[1]); sbuf_printf(sb, "tnlCongDrops: %10u %10u\n", stats.tnl_cong_drops[0], stats.tnl_cong_drops[1]); sbuf_printf(sb, "tnlTxDrops: %10u %10u\n", stats.tnl_tx_drops[0], stats.tnl_tx_drops[1]); sbuf_printf(sb, "ofldVlanDrops: %10u %10u\n", stats.ofld_vlan_drops[0], stats.ofld_vlan_drops[1]); sbuf_printf(sb, "ofldChanDrops: %10u %10u\n\n", stats.ofld_chan_drops[0], stats.ofld_chan_drops[1]); } sbuf_printf(sb, "ofldNoNeigh: %u\nofldCongDefer: %u", stats.ofld_no_neigh, stats.ofld_cong_defer); rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_tp_la_mask(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct tp_params *tpp = &sc->params.tp; u_int mask; int rc; mask = tpp->la_mask >> 16; rc = sysctl_handle_int(oidp, &mask, 0, req); if (rc != 0 || req->newptr == NULL) return (rc); if (mask > 0xffff) return (EINVAL); tpp->la_mask = mask << 16; t4_set_reg_field(sc, A_TP_DBG_LA_CONFIG, 0xffff0000U, tpp->la_mask); return (0); } struct field_desc { const char *name; u_int start; u_int width; }; static void field_desc_show(struct sbuf *sb, uint64_t v, const struct field_desc *f) { char buf[32]; int line_size = 0; while (f->name) { uint64_t mask = (1ULL << f->width) - 1; int len = snprintf(buf, sizeof(buf), "%s: %ju", f->name, ((uintmax_t)v >> f->start) & mask); if (line_size + len >= 79) { line_size = 8; sbuf_printf(sb, "\n "); } sbuf_printf(sb, "%s ", buf); line_size += len + 1; f++; } sbuf_printf(sb, "\n"); } static const struct field_desc tp_la0[] = { { "RcfOpCodeOut", 60, 4 }, { "State", 56, 4 }, { "WcfState", 52, 4 }, { "RcfOpcSrcOut", 50, 2 }, { "CRxError", 49, 1 }, { "ERxError", 48, 1 }, { "SanityFailed", 47, 1 }, { "SpuriousMsg", 46, 1 }, { "FlushInputMsg", 45, 1 }, { "FlushInputCpl", 44, 1 }, { "RssUpBit", 43, 1 }, { "RssFilterHit", 42, 1 }, { "Tid", 32, 10 }, { "InitTcb", 31, 1 }, { "LineNumber", 24, 7 }, { "Emsg", 23, 1 }, { "EdataOut", 22, 1 }, { "Cmsg", 21, 1 }, { "CdataOut", 20, 1 }, { "EreadPdu", 19, 1 }, { "CreadPdu", 18, 1 }, { "TunnelPkt", 17, 1 }, { "RcfPeerFin", 16, 1 }, { "RcfReasonOut", 12, 4 }, { "TxCchannel", 10, 2 }, { "RcfTxChannel", 8, 2 }, { "RxEchannel", 6, 2 }, { "RcfRxChannel", 5, 1 }, { "RcfDataOutSrdy", 4, 1 }, { "RxDvld", 3, 1 }, { "RxOoDvld", 2, 1 }, { "RxCongestion", 1, 1 }, { "TxCongestion", 0, 1 }, { NULL } }; static const struct field_desc tp_la1[] = { { "CplCmdIn", 56, 8 }, { "CplCmdOut", 48, 8 }, { "ESynOut", 47, 1 }, { "EAckOut", 46, 1 }, { "EFinOut", 45, 1 }, { "ERstOut", 44, 1 }, { "SynIn", 43, 1 }, { "AckIn", 42, 1 }, { "FinIn", 41, 1 }, { "RstIn", 40, 1 }, { "DataIn", 39, 1 }, { "DataInVld", 38, 1 }, { "PadIn", 37, 1 }, { "RxBufEmpty", 36, 1 }, { "RxDdp", 35, 1 }, { "RxFbCongestion", 34, 1 }, { "TxFbCongestion", 33, 1 }, { "TxPktSumSrdy", 32, 1 }, { "RcfUlpType", 28, 4 }, { "Eread", 27, 1 }, { "Ebypass", 26, 1 }, { "Esave", 25, 1 }, { "Static0", 24, 1 }, { "Cread", 23, 1 }, { "Cbypass", 22, 1 }, { "Csave", 21, 1 }, { "CPktOut", 20, 1 }, { "RxPagePoolFull", 18, 2 }, { "RxLpbkPkt", 17, 1 }, { "TxLpbkPkt", 16, 1 }, { "RxVfValid", 15, 1 }, { "SynLearned", 14, 1 }, { "SetDelEntry", 13, 1 }, { "SetInvEntry", 12, 1 }, { "CpcmdDvld", 11, 1 }, { "CpcmdSave", 10, 1 }, { "RxPstructsFull", 8, 2 }, { "EpcmdDvld", 7, 1 }, { "EpcmdFlush", 6, 1 }, { "EpcmdTrimPrefix", 5, 1 }, { "EpcmdTrimPostfix", 4, 1 }, { "ERssIp4Pkt", 3, 1 }, { "ERssIp6Pkt", 2, 1 }, { "ERssTcpUdpPkt", 1, 1 }, { "ERssFceFipPkt", 0, 1 }, { NULL } }; static const struct field_desc tp_la2[] = { { "CplCmdIn", 56, 8 }, { "MpsVfVld", 55, 1 }, { "MpsPf", 52, 3 }, { "MpsVf", 44, 8 }, { "SynIn", 43, 1 }, { "AckIn", 42, 1 }, { "FinIn", 41, 1 }, { "RstIn", 40, 1 }, { "DataIn", 39, 1 }, { "DataInVld", 38, 1 }, { "PadIn", 37, 1 }, { "RxBufEmpty", 36, 1 }, { "RxDdp", 35, 1 }, { "RxFbCongestion", 34, 1 }, { "TxFbCongestion", 33, 1 }, { "TxPktSumSrdy", 32, 1 }, { "RcfUlpType", 28, 4 }, { "Eread", 27, 1 }, { "Ebypass", 26, 1 }, { "Esave", 25, 1 }, { "Static0", 24, 1 }, { "Cread", 23, 1 }, { "Cbypass", 22, 1 }, { "Csave", 21, 1 }, { "CPktOut", 20, 1 }, { "RxPagePoolFull", 18, 2 }, { "RxLpbkPkt", 17, 1 }, { "TxLpbkPkt", 16, 1 }, { "RxVfValid", 15, 1 }, { "SynLearned", 14, 1 }, { "SetDelEntry", 13, 1 }, { "SetInvEntry", 12, 1 }, { "CpcmdDvld", 11, 1 }, { "CpcmdSave", 10, 1 }, { "RxPstructsFull", 8, 2 }, { "EpcmdDvld", 7, 1 }, { "EpcmdFlush", 6, 1 }, { "EpcmdTrimPrefix", 5, 1 }, { "EpcmdTrimPostfix", 4, 1 }, { "ERssIp4Pkt", 3, 1 }, { "ERssIp6Pkt", 2, 1 }, { "ERssTcpUdpPkt", 1, 1 }, { "ERssFceFipPkt", 0, 1 }, { NULL } }; static void tp_la_show(struct sbuf *sb, uint64_t *p, int idx) { field_desc_show(sb, *p, tp_la0); } static void tp_la_show2(struct sbuf *sb, uint64_t *p, int idx) { if (idx) sbuf_printf(sb, "\n"); field_desc_show(sb, p[0], tp_la0); if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL) field_desc_show(sb, p[1], tp_la0); } static void tp_la_show3(struct sbuf *sb, uint64_t *p, int idx) { if (idx) sbuf_printf(sb, "\n"); field_desc_show(sb, p[0], tp_la0); if (idx < (TPLA_SIZE / 2 - 1) || p[1] != ~0ULL) field_desc_show(sb, p[1], (p[0] & (1 << 17)) ? tp_la2 : tp_la1); } static int sysctl_tp_la(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; uint64_t *buf, *p; int rc; u_int i, inc; void (*show_func)(struct sbuf *, uint64_t *, int); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(TPLA_SIZE * sizeof(uint64_t), M_CXGBE, M_ZERO | M_WAITOK); t4_tp_read_la(sc, buf, NULL); p = buf; switch (G_DBGLAMODE(t4_read_reg(sc, A_TP_DBG_LA_CONFIG))) { case 2: inc = 2; show_func = tp_la_show2; break; case 3: inc = 2; show_func = tp_la_show3; break; default: inc = 1; show_func = tp_la_show; } for (i = 0; i < TPLA_SIZE / inc; i++, p += inc) (*show_func)(sb, p, i); rc = sbuf_finish(sb); sbuf_delete(sb); free(buf, M_CXGBE); return (rc); } static int sysctl_tx_rate(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc; u64 nrate[MAX_NCHAN], orate[MAX_NCHAN]; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 256, req); if (sb == NULL) return (ENOMEM); t4_get_chan_txrate(sc, nrate, orate); if (sc->chip_params->nchan > 2) { sbuf_printf(sb, " channel 0 channel 1" " channel 2 channel 3\n"); sbuf_printf(sb, "NIC B/s: %10ju %10ju %10ju %10ju\n", nrate[0], nrate[1], nrate[2], nrate[3]); sbuf_printf(sb, "Offload B/s: %10ju %10ju %10ju %10ju", orate[0], orate[1], orate[2], orate[3]); } else { sbuf_printf(sb, " channel 0 channel 1\n"); sbuf_printf(sb, "NIC B/s: %10ju %10ju\n", nrate[0], nrate[1]); sbuf_printf(sb, "Offload B/s: %10ju %10ju", orate[0], orate[1]); } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_ulprx_la(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; uint32_t *buf, *p; int rc, i; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); buf = malloc(ULPRX_LA_SIZE * 8 * sizeof(uint32_t), M_CXGBE, M_ZERO | M_WAITOK); t4_ulprx_read_la(sc, buf); p = buf; sbuf_printf(sb, " Pcmd Type Message" " Data"); for (i = 0; i < ULPRX_LA_SIZE; i++, p += 8) { sbuf_printf(sb, "\n%08x%08x %4x %08x %08x%08x%08x%08x", p[1], p[0], p[2], p[3], p[7], p[6], p[5], p[4]); } rc = sbuf_finish(sb); sbuf_delete(sb); free(buf, M_CXGBE); return (rc); } static int sysctl_wcwr_stats(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct sbuf *sb; int rc, v; MPASS(chip_id(sc) >= CHELSIO_T5); rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); v = t4_read_reg(sc, A_SGE_STAT_CFG); if (G_STATSOURCE_T5(v) == 7) { int mode; mode = is_t5(sc) ? G_STATMODE(v) : G_T6_STATMODE(v); if (mode == 0) { sbuf_printf(sb, "total %d, incomplete %d", t4_read_reg(sc, A_SGE_STAT_TOTAL), t4_read_reg(sc, A_SGE_STAT_MATCH)); } else if (mode == 1) { sbuf_printf(sb, "total %d, data overflow %d", t4_read_reg(sc, A_SGE_STAT_TOTAL), t4_read_reg(sc, A_SGE_STAT_MATCH)); } else { sbuf_printf(sb, "unknown mode %d", mode); } } rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } static int sysctl_tc_params(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; struct tx_cl_rl_params tc; struct sbuf *sb; int i, rc, port_id, mbps, gbps; rc = sysctl_wire_old_buffer(req, 0); if (rc != 0) return (rc); sb = sbuf_new_for_sysctl(NULL, NULL, 4096, req); if (sb == NULL) return (ENOMEM); port_id = arg2 >> 16; MPASS(port_id < sc->params.nports); MPASS(sc->port[port_id] != NULL); i = arg2 & 0xffff; MPASS(i < sc->chip_params->nsched_cls); mtx_lock(&sc->tc_lock); tc = sc->port[port_id]->sched_params->cl_rl[i]; mtx_unlock(&sc->tc_lock); if (tc.flags & TX_CLRL_ERROR) { sbuf_printf(sb, "error"); goto done; } if (tc.ratemode == SCHED_CLASS_RATEMODE_REL) { /* XXX: top speed or actual link speed? */ gbps = port_top_speed(sc->port[port_id]); sbuf_printf(sb, " %u%% of %uGbps", tc.maxrate, gbps); } else if (tc.ratemode == SCHED_CLASS_RATEMODE_ABS) { switch (tc.rateunit) { case SCHED_CLASS_RATEUNIT_BITS: mbps = tc.maxrate / 1000; gbps = tc.maxrate / 1000000; if (tc.maxrate == gbps * 1000000) sbuf_printf(sb, " %uGbps", gbps); else if (tc.maxrate == mbps * 1000) sbuf_printf(sb, " %uMbps", mbps); else sbuf_printf(sb, " %uKbps", tc.maxrate); break; case SCHED_CLASS_RATEUNIT_PKTS: sbuf_printf(sb, " %upps", tc.maxrate); break; default: rc = ENXIO; goto done; } } switch (tc.mode) { case SCHED_CLASS_MODE_CLASS: sbuf_printf(sb, " aggregate"); break; case SCHED_CLASS_MODE_FLOW: sbuf_printf(sb, " per-flow"); break; default: rc = ENXIO; goto done; } done: if (rc == 0) rc = sbuf_finish(sb); sbuf_delete(sb); return (rc); } #endif #ifdef TCP_OFFLOAD static void unit_conv(char *buf, size_t len, u_int val, u_int factor) { u_int rem = val % factor; if (rem == 0) snprintf(buf, len, "%u", val / factor); else { while (rem % 10 == 0) rem /= 10; snprintf(buf, len, "%u.%u", val / factor, rem); } } static int sysctl_tp_tick(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; char buf[16]; u_int res, re; u_int cclk_ps = 1000000000 / sc->params.vpd.cclk; res = t4_read_reg(sc, A_TP_TIMER_RESOLUTION); switch (arg2) { case 0: /* timer_tick */ re = G_TIMERRESOLUTION(res); break; case 1: /* TCP timestamp tick */ re = G_TIMESTAMPRESOLUTION(res); break; case 2: /* DACK tick */ re = G_DELAYEDACKRESOLUTION(res); break; default: return (EDOOFUS); } unit_conv(buf, sizeof(buf), (cclk_ps << re), 1000000); return (sysctl_handle_string(oidp, buf, sizeof(buf), req)); } static int sysctl_tp_dack_timer(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; u_int res, dack_re, v; u_int cclk_ps = 1000000000 / sc->params.vpd.cclk; res = t4_read_reg(sc, A_TP_TIMER_RESOLUTION); dack_re = G_DELAYEDACKRESOLUTION(res); v = ((cclk_ps << dack_re) / 1000000) * t4_read_reg(sc, A_TP_DACK_TIMER); return (sysctl_handle_int(oidp, &v, 0, req)); } static int sysctl_tp_timer(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; int reg = arg2; u_int tre; u_long tp_tick_us, v; u_int cclk_ps = 1000000000 / sc->params.vpd.cclk; MPASS(reg == A_TP_RXT_MIN || reg == A_TP_RXT_MAX || reg == A_TP_PERS_MIN || reg == A_TP_PERS_MAX || reg == A_TP_KEEP_IDLE || reg == A_TP_KEEP_INTVL || reg == A_TP_INIT_SRTT || reg == A_TP_FINWAIT2_TIMER); tre = G_TIMERRESOLUTION(t4_read_reg(sc, A_TP_TIMER_RESOLUTION)); tp_tick_us = (cclk_ps << tre) / 1000000; if (reg == A_TP_INIT_SRTT) v = tp_tick_us * G_INITSRTT(t4_read_reg(sc, reg)); else v = tp_tick_us * t4_read_reg(sc, reg); return (sysctl_handle_long(oidp, &v, 0, req)); } /* * All fields in TP_SHIFT_CNT are 4b and the starting location of the field is * passed to this function. */ static int sysctl_tp_shift_cnt(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; int idx = arg2; u_int v; MPASS(idx >= 0 && idx <= 24); v = (t4_read_reg(sc, A_TP_SHIFT_CNT) >> idx) & 0xf; return (sysctl_handle_int(oidp, &v, 0, req)); } static int sysctl_tp_backoff(SYSCTL_HANDLER_ARGS) { struct adapter *sc = arg1; int idx = arg2; u_int shift, v, r; MPASS(idx >= 0 && idx < 16); r = A_TP_TCP_BACKOFF_REG0 + (idx & ~3); shift = (idx & 3) << 3; v = (t4_read_reg(sc, r) >> shift) & M_TIMERBACKOFFINDEX0; return (sysctl_handle_int(oidp, &v, 0, req)); } #endif static uint32_t fconf_iconf_to_mode(uint32_t fconf, uint32_t iconf) { uint32_t mode; mode = T4_FILTER_IPv4 | T4_FILTER_IPv6 | T4_FILTER_IP_SADDR | T4_FILTER_IP_DADDR | T4_FILTER_IP_SPORT | T4_FILTER_IP_DPORT; if (fconf & F_FRAGMENTATION) mode |= T4_FILTER_IP_FRAGMENT; if (fconf & F_MPSHITTYPE) mode |= T4_FILTER_MPS_HIT_TYPE; if (fconf & F_MACMATCH) mode |= T4_FILTER_MAC_IDX; if (fconf & F_ETHERTYPE) mode |= T4_FILTER_ETH_TYPE; if (fconf & F_PROTOCOL) mode |= T4_FILTER_IP_PROTO; if (fconf & F_TOS) mode |= T4_FILTER_IP_TOS; if (fconf & F_VLAN) mode |= T4_FILTER_VLAN; if (fconf & F_VNIC_ID) { mode |= T4_FILTER_VNIC; if (iconf & F_VNIC) mode |= T4_FILTER_IC_VNIC; } if (fconf & F_PORT) mode |= T4_FILTER_PORT; if (fconf & F_FCOE) mode |= T4_FILTER_FCoE; return (mode); } static uint32_t mode_to_fconf(uint32_t mode) { uint32_t fconf = 0; if (mode & T4_FILTER_IP_FRAGMENT) fconf |= F_FRAGMENTATION; if (mode & T4_FILTER_MPS_HIT_TYPE) fconf |= F_MPSHITTYPE; if (mode & T4_FILTER_MAC_IDX) fconf |= F_MACMATCH; if (mode & T4_FILTER_ETH_TYPE) fconf |= F_ETHERTYPE; if (mode & T4_FILTER_IP_PROTO) fconf |= F_PROTOCOL; if (mode & T4_FILTER_IP_TOS) fconf |= F_TOS; if (mode & T4_FILTER_VLAN) fconf |= F_VLAN; if (mode & T4_FILTER_VNIC) fconf |= F_VNIC_ID; if (mode & T4_FILTER_PORT) fconf |= F_PORT; if (mode & T4_FILTER_FCoE) fconf |= F_FCOE; return (fconf); } static uint32_t mode_to_iconf(uint32_t mode) { if (mode & T4_FILTER_IC_VNIC) return (F_VNIC); return (0); } static int check_fspec_against_fconf_iconf(struct adapter *sc, struct t4_filter_specification *fs) { struct tp_params *tpp = &sc->params.tp; uint32_t fconf = 0; if (fs->val.frag || fs->mask.frag) fconf |= F_FRAGMENTATION; if (fs->val.matchtype || fs->mask.matchtype) fconf |= F_MPSHITTYPE; if (fs->val.macidx || fs->mask.macidx) fconf |= F_MACMATCH; if (fs->val.ethtype || fs->mask.ethtype) fconf |= F_ETHERTYPE; if (fs->val.proto || fs->mask.proto) fconf |= F_PROTOCOL; if (fs->val.tos || fs->mask.tos) fconf |= F_TOS; if (fs->val.vlan_vld || fs->mask.vlan_vld) fconf |= F_VLAN; if (fs->val.ovlan_vld || fs->mask.ovlan_vld) { fconf |= F_VNIC_ID; if (tpp->ingress_config & F_VNIC) return (EINVAL); } if (fs->val.pfvf_vld || fs->mask.pfvf_vld) { fconf |= F_VNIC_ID; if ((tpp->ingress_config & F_VNIC) == 0) return (EINVAL); } if (fs->val.iport || fs->mask.iport) fconf |= F_PORT; if (fs->val.fcoe || fs->mask.fcoe) fconf |= F_FCOE; if ((tpp->vlan_pri_map | fconf) != tpp->vlan_pri_map) return (E2BIG); return (0); } static int get_filter_mode(struct adapter *sc, uint32_t *mode) { struct tp_params *tpp = &sc->params.tp; /* * We trust the cached values of the relevant TP registers. This means * things work reliably only if writes to those registers are always via * t4_set_filter_mode. */ *mode = fconf_iconf_to_mode(tpp->vlan_pri_map, tpp->ingress_config); return (0); } static int set_filter_mode(struct adapter *sc, uint32_t mode) { struct tp_params *tpp = &sc->params.tp; uint32_t fconf, iconf; int rc; iconf = mode_to_iconf(mode); if ((iconf ^ tpp->ingress_config) & F_VNIC) { /* * For now we just complain if A_TP_INGRESS_CONFIG is not * already set to the correct value for the requested filter * mode. It's not clear if it's safe to write to this register * on the fly. (And we trust the cached value of the register). */ return (EBUSY); } fconf = mode_to_fconf(mode); rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4setfm"); if (rc) return (rc); if (sc->tids.ftids_in_use > 0) { rc = EBUSY; goto done; } #ifdef TCP_OFFLOAD if (uld_active(sc, ULD_TOM)) { rc = EBUSY; goto done; } #endif rc = -t4_set_filter_mode(sc, fconf, true); done: end_synchronized_op(sc, LOCK_HELD); return (rc); } static inline uint64_t get_filter_hits(struct adapter *sc, uint32_t fid) { uint32_t tcb_addr; tcb_addr = t4_read_reg(sc, A_TP_CMM_TCB_BASE) + (fid + sc->tids.ftid_base) * TCB_SIZE; if (is_t4(sc)) { uint64_t hits; read_via_memwin(sc, 0, tcb_addr + 16, (uint32_t *)&hits, 8); return (be64toh(hits)); } else { uint32_t hits; read_via_memwin(sc, 0, tcb_addr + 24, &hits, 4); return (be32toh(hits)); } } static int get_filter(struct adapter *sc, struct t4_filter *t) { int i, rc, nfilters = sc->tids.nftids; struct filter_entry *f; rc = begin_synchronized_op(sc, NULL, HOLD_LOCK | SLEEP_OK | INTR_OK, "t4getf"); if (rc) return (rc); if (sc->tids.ftids_in_use == 0 || sc->tids.ftid_tab == NULL || t->idx >= nfilters) { t->idx = 0xffffffff; goto done; } f = &sc->tids.ftid_tab[t->idx]; for (i = t->idx; i < nfilters; i++, f++) { if (f->valid) { t->idx = i; t->l2tidx = f->l2t ? f->l2t->idx : 0; t->smtidx = f->smtidx; if (f->fs.hitcnts) t->hits = get_filter_hits(sc, t->idx); else t->hits = UINT64_MAX; t->fs = f->fs; goto done; } } t->idx = 0xffffffff; done: end_synchronized_op(sc, LOCK_HELD); return (0); } static int set_filter(struct adapter *sc, struct t4_filter *t) { unsigned int nfilters, nports; struct filter_entry *f; int i, rc; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4setf"); if (rc) return (rc); nfilters = sc->tids.nftids; nports = sc->params.nports; if (nfilters == 0) { rc = ENOTSUP; goto done; } if (t->idx >= nfilters) { rc = EINVAL; goto done; } /* Validate against the global filter mode and ingress config */ rc = check_fspec_against_fconf_iconf(sc, &t->fs); if (rc != 0) goto done; if (t->fs.action == FILTER_SWITCH && t->fs.eport >= nports) { rc = EINVAL; goto done; } if (t->fs.val.iport >= nports) { rc = EINVAL; goto done; } /* Can't specify an iq if not steering to it */ if (!t->fs.dirsteer && t->fs.iq) { rc = EINVAL; goto done; } /* IPv6 filter idx must be 4 aligned */ if (t->fs.type == 1 && ((t->idx & 0x3) || t->idx + 4 >= nfilters)) { rc = EINVAL; goto done; } if (!(sc->flags & FULL_INIT_DONE) && ((rc = adapter_full_init(sc)) != 0)) goto done; if (sc->tids.ftid_tab == NULL) { KASSERT(sc->tids.ftids_in_use == 0, ("%s: no memory allocated but filters_in_use > 0", __func__)); sc->tids.ftid_tab = malloc(sizeof (struct filter_entry) * nfilters, M_CXGBE, M_NOWAIT | M_ZERO); if (sc->tids.ftid_tab == NULL) { rc = ENOMEM; goto done; } mtx_init(&sc->tids.ftid_lock, "T4 filters", 0, MTX_DEF); } for (i = 0; i < 4; i++) { f = &sc->tids.ftid_tab[t->idx + i]; if (f->pending || f->valid) { rc = EBUSY; goto done; } if (f->locked) { rc = EPERM; goto done; } if (t->fs.type == 0) break; } f = &sc->tids.ftid_tab[t->idx]; f->fs = t->fs; rc = set_filter_wr(sc, t->idx); done: end_synchronized_op(sc, 0); if (rc == 0) { mtx_lock(&sc->tids.ftid_lock); for (;;) { if (f->pending == 0) { rc = f->valid ? 0 : EIO; break; } if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock, PCATCH, "t4setfw", 0)) { rc = EINPROGRESS; break; } } mtx_unlock(&sc->tids.ftid_lock); } return (rc); } static int del_filter(struct adapter *sc, struct t4_filter *t) { unsigned int nfilters; struct filter_entry *f; int rc; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4delf"); if (rc) return (rc); nfilters = sc->tids.nftids; if (nfilters == 0) { rc = ENOTSUP; goto done; } if (sc->tids.ftid_tab == NULL || sc->tids.ftids_in_use == 0 || t->idx >= nfilters) { rc = EINVAL; goto done; } if (!(sc->flags & FULL_INIT_DONE)) { rc = EAGAIN; goto done; } f = &sc->tids.ftid_tab[t->idx]; if (f->pending) { rc = EBUSY; goto done; } if (f->locked) { rc = EPERM; goto done; } if (f->valid) { t->fs = f->fs; /* extra info for the caller */ rc = del_filter_wr(sc, t->idx); } done: end_synchronized_op(sc, 0); if (rc == 0) { mtx_lock(&sc->tids.ftid_lock); for (;;) { if (f->pending == 0) { rc = f->valid ? EIO : 0; break; } if (mtx_sleep(&sc->tids.ftid_tab, &sc->tids.ftid_lock, PCATCH, "t4delfw", 0)) { rc = EINPROGRESS; break; } } mtx_unlock(&sc->tids.ftid_lock); } return (rc); } static void clear_filter(struct filter_entry *f) { if (f->l2t) t4_l2t_release(f->l2t); bzero(f, sizeof (*f)); } static int set_filter_wr(struct adapter *sc, int fidx) { struct filter_entry *f = &sc->tids.ftid_tab[fidx]; struct fw_filter_wr *fwr; unsigned int ftid, vnic_vld, vnic_vld_mask; struct wrq_cookie cookie; ASSERT_SYNCHRONIZED_OP(sc); if (f->fs.newdmac || f->fs.newvlan) { /* This filter needs an L2T entry; allocate one. */ f->l2t = t4_l2t_alloc_switching(sc->l2t); if (f->l2t == NULL) return (EAGAIN); if (t4_l2t_set_switching(sc, f->l2t, f->fs.vlan, f->fs.eport, f->fs.dmac)) { t4_l2t_release(f->l2t); f->l2t = NULL; return (ENOMEM); } } /* Already validated against fconf, iconf */ MPASS((f->fs.val.pfvf_vld & f->fs.val.ovlan_vld) == 0); MPASS((f->fs.mask.pfvf_vld & f->fs.mask.ovlan_vld) == 0); if (f->fs.val.pfvf_vld || f->fs.val.ovlan_vld) vnic_vld = 1; else vnic_vld = 0; if (f->fs.mask.pfvf_vld || f->fs.mask.ovlan_vld) vnic_vld_mask = 1; else vnic_vld_mask = 0; ftid = sc->tids.ftid_base + fidx; fwr = start_wrq_wr(&sc->sge.mgmtq, howmany(sizeof(*fwr), 16), &cookie); if (fwr == NULL) return (ENOMEM); bzero(fwr, sizeof(*fwr)); fwr->op_pkd = htobe32(V_FW_WR_OP(FW_FILTER_WR)); fwr->len16_pkd = htobe32(FW_LEN16(*fwr)); fwr->tid_to_iq = htobe32(V_FW_FILTER_WR_TID(ftid) | V_FW_FILTER_WR_RQTYPE(f->fs.type) | V_FW_FILTER_WR_NOREPLY(0) | V_FW_FILTER_WR_IQ(f->fs.iq)); fwr->del_filter_to_l2tix = htobe32(V_FW_FILTER_WR_RPTTID(f->fs.rpttid) | V_FW_FILTER_WR_DROP(f->fs.action == FILTER_DROP) | V_FW_FILTER_WR_DIRSTEER(f->fs.dirsteer) | V_FW_FILTER_WR_MASKHASH(f->fs.maskhash) | V_FW_FILTER_WR_DIRSTEERHASH(f->fs.dirsteerhash) | V_FW_FILTER_WR_LPBK(f->fs.action == FILTER_SWITCH) | V_FW_FILTER_WR_DMAC(f->fs.newdmac) | V_FW_FILTER_WR_SMAC(f->fs.newsmac) | V_FW_FILTER_WR_INSVLAN(f->fs.newvlan == VLAN_INSERT || f->fs.newvlan == VLAN_REWRITE) | V_FW_FILTER_WR_RMVLAN(f->fs.newvlan == VLAN_REMOVE || f->fs.newvlan == VLAN_REWRITE) | V_FW_FILTER_WR_HITCNTS(f->fs.hitcnts) | V_FW_FILTER_WR_TXCHAN(f->fs.eport) | V_FW_FILTER_WR_PRIO(f->fs.prio) | V_FW_FILTER_WR_L2TIX(f->l2t ? f->l2t->idx : 0)); fwr->ethtype = htobe16(f->fs.val.ethtype); fwr->ethtypem = htobe16(f->fs.mask.ethtype); fwr->frag_to_ovlan_vldm = (V_FW_FILTER_WR_FRAG(f->fs.val.frag) | V_FW_FILTER_WR_FRAGM(f->fs.mask.frag) | V_FW_FILTER_WR_IVLAN_VLD(f->fs.val.vlan_vld) | V_FW_FILTER_WR_OVLAN_VLD(vnic_vld) | V_FW_FILTER_WR_IVLAN_VLDM(f->fs.mask.vlan_vld) | V_FW_FILTER_WR_OVLAN_VLDM(vnic_vld_mask)); fwr->smac_sel = 0; fwr->rx_chan_rx_rpl_iq = htobe16(V_FW_FILTER_WR_RX_CHAN(0) | V_FW_FILTER_WR_RX_RPL_IQ(sc->sge.fwq.abs_id)); fwr->maci_to_matchtypem = htobe32(V_FW_FILTER_WR_MACI(f->fs.val.macidx) | V_FW_FILTER_WR_MACIM(f->fs.mask.macidx) | V_FW_FILTER_WR_FCOE(f->fs.val.fcoe) | V_FW_FILTER_WR_FCOEM(f->fs.mask.fcoe) | V_FW_FILTER_WR_PORT(f->fs.val.iport) | V_FW_FILTER_WR_PORTM(f->fs.mask.iport) | V_FW_FILTER_WR_MATCHTYPE(f->fs.val.matchtype) | V_FW_FILTER_WR_MATCHTYPEM(f->fs.mask.matchtype)); fwr->ptcl = f->fs.val.proto; fwr->ptclm = f->fs.mask.proto; fwr->ttyp = f->fs.val.tos; fwr->ttypm = f->fs.mask.tos; fwr->ivlan = htobe16(f->fs.val.vlan); fwr->ivlanm = htobe16(f->fs.mask.vlan); fwr->ovlan = htobe16(f->fs.val.vnic); fwr->ovlanm = htobe16(f->fs.mask.vnic); bcopy(f->fs.val.dip, fwr->lip, sizeof (fwr->lip)); bcopy(f->fs.mask.dip, fwr->lipm, sizeof (fwr->lipm)); bcopy(f->fs.val.sip, fwr->fip, sizeof (fwr->fip)); bcopy(f->fs.mask.sip, fwr->fipm, sizeof (fwr->fipm)); fwr->lp = htobe16(f->fs.val.dport); fwr->lpm = htobe16(f->fs.mask.dport); fwr->fp = htobe16(f->fs.val.sport); fwr->fpm = htobe16(f->fs.mask.sport); if (f->fs.newsmac) bcopy(f->fs.smac, fwr->sma, sizeof (fwr->sma)); f->pending = 1; sc->tids.ftids_in_use++; commit_wrq_wr(&sc->sge.mgmtq, fwr, &cookie); return (0); } static int del_filter_wr(struct adapter *sc, int fidx) { struct filter_entry *f = &sc->tids.ftid_tab[fidx]; struct fw_filter_wr *fwr; unsigned int ftid; struct wrq_cookie cookie; ftid = sc->tids.ftid_base + fidx; fwr = start_wrq_wr(&sc->sge.mgmtq, howmany(sizeof(*fwr), 16), &cookie); if (fwr == NULL) return (ENOMEM); bzero(fwr, sizeof (*fwr)); t4_mk_filtdelwr(ftid, fwr, sc->sge.fwq.abs_id); f->pending = 1; commit_wrq_wr(&sc->sge.mgmtq, fwr, &cookie); return (0); } int t4_filter_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) { struct adapter *sc = iq->adapter; const struct cpl_set_tcb_rpl *rpl = (const void *)(rss + 1); unsigned int idx = GET_TID(rpl); unsigned int rc; struct filter_entry *f; KASSERT(m == NULL, ("%s: payload with opcode %02x", __func__, rss->opcode)); MPASS(iq == &sc->sge.fwq); MPASS(is_ftid(sc, idx)); idx -= sc->tids.ftid_base; f = &sc->tids.ftid_tab[idx]; rc = G_COOKIE(rpl->cookie); mtx_lock(&sc->tids.ftid_lock); if (rc == FW_FILTER_WR_FLT_ADDED) { KASSERT(f->pending, ("%s: filter[%u] isn't pending.", __func__, idx)); f->smtidx = (be64toh(rpl->oldval) >> 24) & 0xff; f->pending = 0; /* asynchronous setup completed */ f->valid = 1; } else { if (rc != FW_FILTER_WR_FLT_DELETED) { /* Add or delete failed, display an error */ log(LOG_ERR, "filter %u setup failed with error %u\n", idx, rc); } clear_filter(f); sc->tids.ftids_in_use--; } wakeup(&sc->tids.ftid_tab); mtx_unlock(&sc->tids.ftid_lock); return (0); } static int set_tcb_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) { MPASS(iq->set_tcb_rpl != NULL); return (iq->set_tcb_rpl(iq, rss, m)); } static int l2t_write_rpl(struct sge_iq *iq, const struct rss_header *rss, struct mbuf *m) { MPASS(iq->l2t_write_rpl != NULL); return (iq->l2t_write_rpl(iq, rss, m)); } static int get_sge_context(struct adapter *sc, struct t4_sge_context *cntxt) { int rc; if (cntxt->cid > M_CTXTQID) return (EINVAL); if (cntxt->mem_id != CTXT_EGRESS && cntxt->mem_id != CTXT_INGRESS && cntxt->mem_id != CTXT_FLM && cntxt->mem_id != CTXT_CNM) return (EINVAL); rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ctxt"); if (rc) return (rc); if (sc->flags & FW_OK) { rc = -t4_sge_ctxt_rd(sc, sc->mbox, cntxt->cid, cntxt->mem_id, &cntxt->data[0]); if (rc == 0) goto done; } /* * Read via firmware failed or wasn't even attempted. Read directly via * the backdoor. */ rc = -t4_sge_ctxt_rd_bd(sc, cntxt->cid, cntxt->mem_id, &cntxt->data[0]); done: end_synchronized_op(sc, 0); return (rc); } static int load_fw(struct adapter *sc, struct t4_data *fw) { int rc; uint8_t *fw_data; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldfw"); if (rc) return (rc); if (sc->flags & FULL_INIT_DONE) { rc = EBUSY; goto done; } fw_data = malloc(fw->len, M_CXGBE, M_WAITOK); if (fw_data == NULL) { rc = ENOMEM; goto done; } rc = copyin(fw->data, fw_data, fw->len); if (rc == 0) rc = -t4_load_fw(sc, fw_data, fw->len); free(fw_data, M_CXGBE); done: end_synchronized_op(sc, 0); return (rc); } static int load_cfg(struct adapter *sc, struct t4_data *cfg) { int rc; uint8_t *cfg_data = NULL; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldcf"); if (rc) return (rc); if (cfg->len == 0) { /* clear */ rc = -t4_load_cfg(sc, NULL, 0); goto done; } cfg_data = malloc(cfg->len, M_CXGBE, M_WAITOK); if (cfg_data == NULL) { rc = ENOMEM; goto done; } rc = copyin(cfg->data, cfg_data, cfg->len); if (rc == 0) rc = -t4_load_cfg(sc, cfg_data, cfg->len); free(cfg_data, M_CXGBE); done: end_synchronized_op(sc, 0); return (rc); } static int load_boot(struct adapter *sc, struct t4_bootrom *br) { int rc; uint8_t *br_data = NULL; u_int offset; if (br->len > 1024 * 1024) return (EFBIG); if (br->pf_offset == 0) { /* pfidx */ if (br->pfidx_addr > 7) return (EINVAL); offset = G_OFFSET(t4_read_reg(sc, PF_REG(br->pfidx_addr, A_PCIE_PF_EXPROM_OFST))); } else if (br->pf_offset == 1) { /* offset */ offset = G_OFFSET(br->pfidx_addr); } else { return (EINVAL); } rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldbr"); if (rc) return (rc); if (br->len == 0) { /* clear */ rc = -t4_load_boot(sc, NULL, offset, 0); goto done; } br_data = malloc(br->len, M_CXGBE, M_WAITOK); if (br_data == NULL) { rc = ENOMEM; goto done; } rc = copyin(br->data, br_data, br->len); if (rc == 0) rc = -t4_load_boot(sc, br_data, offset, br->len); free(br_data, M_CXGBE); done: end_synchronized_op(sc, 0); return (rc); } static int load_bootcfg(struct adapter *sc, struct t4_data *bc) { int rc; uint8_t *bc_data = NULL; rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4ldcf"); if (rc) return (rc); if (bc->len == 0) { /* clear */ rc = -t4_load_bootcfg(sc, NULL, 0); goto done; } bc_data = malloc(bc->len, M_CXGBE, M_WAITOK); if (bc_data == NULL) { rc = ENOMEM; goto done; } rc = copyin(bc->data, bc_data, bc->len); if (rc == 0) rc = -t4_load_bootcfg(sc, bc_data, bc->len); free(bc_data, M_CXGBE); done: end_synchronized_op(sc, 0); return (rc); } +static int +cudbg_dump(struct adapter *sc, struct t4_cudbg_dump *dump) +{ + int rc; + struct cudbg_init *cudbg; + void *handle, *buf; + + /* buf is large, don't block if no memory is available */ + buf = malloc(dump->len, M_CXGBE, M_NOWAIT); + if (buf == NULL) + return (ENOMEM); + + handle = cudbg_alloc_handle(); + if (handle == NULL) { + rc = ENOMEM; + goto done; + } + + cudbg = cudbg_get_init(handle); + cudbg->adap = sc; + cudbg->print = (cudbg_print_cb)printf; + +#ifndef notyet + device_printf(sc->dev, "%s: wr_flash %u, len %u, data %p.\n", + __func__, dump->wr_flash, dump->len, dump->data); +#endif + + if (dump->wr_flash) + cudbg->use_flash = 1; + MPASS(sizeof(cudbg->dbg_bitmap) == sizeof(dump->bitmap)); + memcpy(cudbg->dbg_bitmap, dump->bitmap, sizeof(cudbg->dbg_bitmap)); + + rc = cudbg_collect(handle, buf, &dump->len); + if (rc != 0) + goto done; + + rc = copyout(buf, dump->data, dump->len); +done: + cudbg_free_handle(handle); + free(buf, M_CXGBE); + return (rc); +} + #define MAX_READ_BUF_SIZE (128 * 1024) static int read_card_mem(struct adapter *sc, int win, struct t4_mem_range *mr) { uint32_t addr, remaining, n; uint32_t *buf; int rc; uint8_t *dst; rc = validate_mem_range(sc, mr->addr, mr->len); if (rc != 0) return (rc); buf = malloc(min(mr->len, MAX_READ_BUF_SIZE), M_CXGBE, M_WAITOK); addr = mr->addr; remaining = mr->len; dst = (void *)mr->data; while (remaining) { n = min(remaining, MAX_READ_BUF_SIZE); read_via_memwin(sc, 2, addr, buf, n); rc = copyout(buf, dst, n); if (rc != 0) break; dst += n; remaining -= n; addr += n; } free(buf, M_CXGBE); return (rc); } #undef MAX_READ_BUF_SIZE static int read_i2c(struct adapter *sc, struct t4_i2c_data *i2cd) { int rc; if (i2cd->len == 0 || i2cd->port_id >= sc->params.nports) return (EINVAL); if (i2cd->len > sizeof(i2cd->data)) return (EFBIG); rc = begin_synchronized_op(sc, NULL, SLEEP_OK | INTR_OK, "t4i2crd"); if (rc) return (rc); rc = -t4_i2c_rd(sc, sc->mbox, i2cd->port_id, i2cd->dev_addr, i2cd->offset, i2cd->len, &i2cd->data[0]); end_synchronized_op(sc, 0); return (rc); } int t4_os_find_pci_capability(struct adapter *sc, int cap) { int i; return (pci_find_cap(sc->dev, cap, &i) == 0 ? i : 0); } int t4_os_pci_save_state(struct adapter *sc) { device_t dev; struct pci_devinfo *dinfo; dev = sc->dev; dinfo = device_get_ivars(dev); pci_cfg_save(dev, dinfo, 0); return (0); } int t4_os_pci_restore_state(struct adapter *sc) { device_t dev; struct pci_devinfo *dinfo; dev = sc->dev; dinfo = device_get_ivars(dev); pci_cfg_restore(dev, dinfo); return (0); } void t4_os_portmod_changed(struct port_info *pi, int old_ptype, int old_mtype, struct link_config *old_lc) { struct vi_info *vi; struct ifnet *ifp; int v; static const char *mod_str[] = { NULL, "LR", "SR", "ER", "TWINAX", "active TWINAX", "LRM" }; PORT_LOCK(pi); for_each_vi(pi, v, vi) { build_medialist(pi, &vi->media); } PORT_UNLOCK(pi); if (begin_synchronized_op(pi->adapter, vi, HOLD_LOCK, "t4mod") == 0) { init_l1cfg(pi); end_synchronized_op(pi->adapter, LOCK_HELD); } ifp = pi->vi[0].ifp; if (pi->mod_type == FW_PORT_MOD_TYPE_NONE) if_printf(ifp, "transceiver unplugged.\n"); else if (pi->mod_type == FW_PORT_MOD_TYPE_UNKNOWN) if_printf(ifp, "unknown transceiver inserted.\n"); else if (pi->mod_type == FW_PORT_MOD_TYPE_NOTSUPPORTED) if_printf(ifp, "unsupported transceiver inserted.\n"); else if (pi->mod_type > 0 && pi->mod_type < nitems(mod_str)) { if_printf(ifp, "%dGbps %s transceiver inserted.\n", port_top_speed(pi), mod_str[pi->mod_type]); } else { if_printf(ifp, "transceiver (type %d) inserted.\n", pi->mod_type); } } void t4_os_link_changed(struct port_info *pi, struct link_config *old_lc) { struct vi_info *vi; struct ifnet *ifp; struct link_config *lc; int v; for_each_vi(pi, v, vi) { ifp = vi->ifp; if (ifp == NULL) continue; lc = &pi->link_cfg; if (lc->link_ok) { ifp->if_baudrate = IF_Mbps(lc->speed); if_link_state_change(ifp, LINK_STATE_UP); } else { if_link_state_change(ifp, LINK_STATE_DOWN); } } } void t4_iterate(void (*func)(struct adapter *, void *), void *arg) { struct adapter *sc; sx_slock(&t4_list_lock); SLIST_FOREACH(sc, &t4_list, link) { /* * func should not make any assumptions about what state sc is * in - the only guarantee is that sc->sc_lock is a valid lock. */ func(sc, arg); } sx_sunlock(&t4_list_lock); } static int t4_ioctl(struct cdev *dev, unsigned long cmd, caddr_t data, int fflag, struct thread *td) { int rc; struct adapter *sc = dev->si_drv1; rc = priv_check(td, PRIV_DRIVER); if (rc != 0) return (rc); switch (cmd) { case CHELSIO_T4_GETREG: { struct t4_reg *edata = (struct t4_reg *)data; if ((edata->addr & 0x3) != 0 || edata->addr >= sc->mmio_len) return (EFAULT); if (edata->size == 4) edata->val = t4_read_reg(sc, edata->addr); else if (edata->size == 8) edata->val = t4_read_reg64(sc, edata->addr); else return (EINVAL); break; } case CHELSIO_T4_SETREG: { struct t4_reg *edata = (struct t4_reg *)data; if ((edata->addr & 0x3) != 0 || edata->addr >= sc->mmio_len) return (EFAULT); if (edata->size == 4) { if (edata->val & 0xffffffff00000000) return (EINVAL); t4_write_reg(sc, edata->addr, (uint32_t) edata->val); } else if (edata->size == 8) t4_write_reg64(sc, edata->addr, edata->val); else return (EINVAL); break; } case CHELSIO_T4_REGDUMP: { struct t4_regdump *regs = (struct t4_regdump *)data; int reglen = t4_get_regs_len(sc); uint8_t *buf; if (regs->len < reglen) { regs->len = reglen; /* hint to the caller */ return (ENOBUFS); } regs->len = reglen; buf = malloc(reglen, M_CXGBE, M_WAITOK | M_ZERO); get_regs(sc, regs, buf); rc = copyout(buf, regs->data, reglen); free(buf, M_CXGBE); break; } case CHELSIO_T4_GET_FILTER_MODE: rc = get_filter_mode(sc, (uint32_t *)data); break; case CHELSIO_T4_SET_FILTER_MODE: rc = set_filter_mode(sc, *(uint32_t *)data); break; case CHELSIO_T4_GET_FILTER: rc = get_filter(sc, (struct t4_filter *)data); break; case CHELSIO_T4_SET_FILTER: rc = set_filter(sc, (struct t4_filter *)data); break; case CHELSIO_T4_DEL_FILTER: rc = del_filter(sc, (struct t4_filter *)data); break; case CHELSIO_T4_GET_SGE_CONTEXT: rc = get_sge_context(sc, (struct t4_sge_context *)data); break; case CHELSIO_T4_LOAD_FW: rc = load_fw(sc, (struct t4_data *)data); break; case CHELSIO_T4_GET_MEM: rc = read_card_mem(sc, 2, (struct t4_mem_range *)data); break; case CHELSIO_T4_GET_I2C: rc = read_i2c(sc, (struct t4_i2c_data *)data); break; case CHELSIO_T4_CLEAR_STATS: { int i, v; u_int port_id = *(uint32_t *)data; struct port_info *pi; struct vi_info *vi; if (port_id >= sc->params.nports) return (EINVAL); pi = sc->port[port_id]; if (pi == NULL) return (EIO); /* MAC stats */ t4_clr_port_stats(sc, pi->tx_chan); pi->tx_parse_error = 0; mtx_lock(&sc->reg_lock); for_each_vi(pi, v, vi) { if (vi->flags & VI_INIT_DONE) t4_clr_vi_stats(sc, vi->viid); } mtx_unlock(&sc->reg_lock); /* * Since this command accepts a port, clear stats for * all VIs on this port. */ for_each_vi(pi, v, vi) { if (vi->flags & VI_INIT_DONE) { struct sge_rxq *rxq; struct sge_txq *txq; struct sge_wrq *wrq; for_each_rxq(vi, i, rxq) { #if defined(INET) || defined(INET6) rxq->lro.lro_queued = 0; rxq->lro.lro_flushed = 0; #endif rxq->rxcsum = 0; rxq->vlan_extraction = 0; } for_each_txq(vi, i, txq) { txq->txcsum = 0; txq->tso_wrs = 0; txq->vlan_insertion = 0; txq->imm_wrs = 0; txq->sgl_wrs = 0; txq->txpkt_wrs = 0; txq->txpkts0_wrs = 0; txq->txpkts1_wrs = 0; txq->txpkts0_pkts = 0; txq->txpkts1_pkts = 0; mp_ring_reset_stats(txq->r); } #ifdef TCP_OFFLOAD /* nothing to clear for each ofld_rxq */ for_each_ofld_txq(vi, i, wrq) { wrq->tx_wrs_direct = 0; wrq->tx_wrs_copied = 0; } #endif if (IS_MAIN_VI(vi)) { wrq = &sc->sge.ctrlq[pi->port_id]; wrq->tx_wrs_direct = 0; wrq->tx_wrs_copied = 0; } } } break; } case CHELSIO_T4_SCHED_CLASS: rc = t4_set_sched_class(sc, (struct t4_sched_params *)data); break; case CHELSIO_T4_SCHED_QUEUE: rc = t4_set_sched_queue(sc, (struct t4_sched_queue *)data); break; case CHELSIO_T4_GET_TRACER: rc = t4_get_tracer(sc, (struct t4_tracer *)data); break; case CHELSIO_T4_SET_TRACER: rc = t4_set_tracer(sc, (struct t4_tracer *)data); break; case CHELSIO_T4_LOAD_CFG: rc = load_cfg(sc, (struct t4_data *)data); break; case CHELSIO_T4_LOAD_BOOT: rc = load_boot(sc, (struct t4_bootrom *)data); break; case CHELSIO_T4_LOAD_BOOTCFG: rc = load_bootcfg(sc, (struct t4_data *)data); + break; + case CHELSIO_T4_CUDBG_DUMP: + rc = cudbg_dump(sc, (struct t4_cudbg_dump *)data); break; default: rc = ENOTTY; } return (rc); } void t4_db_full(struct adapter *sc) { CXGBE_UNIMPLEMENTED(__func__); } void t4_db_dropped(struct adapter *sc) { CXGBE_UNIMPLEMENTED(__func__); } #ifdef TCP_OFFLOAD static int toe_capability(struct vi_info *vi, int enable) { int rc; struct port_info *pi = vi->pi; struct adapter *sc = pi->adapter; ASSERT_SYNCHRONIZED_OP(sc); if (!is_offload(sc)) return (ENODEV); if (enable) { if ((vi->ifp->if_capenable & IFCAP_TOE) != 0) { /* TOE is already enabled. */ return (0); } /* * We need the port's queues around so that we're able to send * and receive CPLs to/from the TOE even if the ifnet for this * port has never been UP'd administratively. */ if (!(vi->flags & VI_INIT_DONE)) { rc = vi_full_init(vi); if (rc) return (rc); } if (!(pi->vi[0].flags & VI_INIT_DONE)) { rc = vi_full_init(&pi->vi[0]); if (rc) return (rc); } if (isset(&sc->offload_map, pi->port_id)) { /* TOE is enabled on another VI of this port. */ pi->uld_vis++; return (0); } if (!uld_active(sc, ULD_TOM)) { rc = t4_activate_uld(sc, ULD_TOM); if (rc == EAGAIN) { log(LOG_WARNING, "You must kldload t4_tom.ko before trying " "to enable TOE on a cxgbe interface.\n"); } if (rc != 0) return (rc); KASSERT(sc->tom_softc != NULL, ("%s: TOM activated but softc NULL", __func__)); KASSERT(uld_active(sc, ULD_TOM), ("%s: TOM activated but flag not set", __func__)); } /* Activate iWARP and iSCSI too, if the modules are loaded. */ if (!uld_active(sc, ULD_IWARP)) (void) t4_activate_uld(sc, ULD_IWARP); if (!uld_active(sc, ULD_ISCSI)) (void) t4_activate_uld(sc, ULD_ISCSI); pi->uld_vis++; setbit(&sc->offload_map, pi->port_id); } else { pi->uld_vis--; if (!isset(&sc->offload_map, pi->port_id) || pi->uld_vis > 0) return (0); KASSERT(uld_active(sc, ULD_TOM), ("%s: TOM never initialized?", __func__)); clrbit(&sc->offload_map, pi->port_id); } return (0); } /* * Add an upper layer driver to the global list. */ int t4_register_uld(struct uld_info *ui) { int rc = 0; struct uld_info *u; sx_xlock(&t4_uld_list_lock); SLIST_FOREACH(u, &t4_uld_list, link) { if (u->uld_id == ui->uld_id) { rc = EEXIST; goto done; } } SLIST_INSERT_HEAD(&t4_uld_list, ui, link); ui->refcount = 0; done: sx_xunlock(&t4_uld_list_lock); return (rc); } int t4_unregister_uld(struct uld_info *ui) { int rc = EINVAL; struct uld_info *u; sx_xlock(&t4_uld_list_lock); SLIST_FOREACH(u, &t4_uld_list, link) { if (u == ui) { if (ui->refcount > 0) { rc = EBUSY; goto done; } SLIST_REMOVE(&t4_uld_list, ui, uld_info, link); rc = 0; goto done; } } done: sx_xunlock(&t4_uld_list_lock); return (rc); } int t4_activate_uld(struct adapter *sc, int id) { int rc; struct uld_info *ui; ASSERT_SYNCHRONIZED_OP(sc); if (id < 0 || id > ULD_MAX) return (EINVAL); rc = EAGAIN; /* kldoad the module with this ULD and try again. */ sx_slock(&t4_uld_list_lock); SLIST_FOREACH(ui, &t4_uld_list, link) { if (ui->uld_id == id) { if (!(sc->flags & FULL_INIT_DONE)) { rc = adapter_full_init(sc); if (rc != 0) break; } rc = ui->activate(sc); if (rc == 0) { setbit(&sc->active_ulds, id); ui->refcount++; } break; } } sx_sunlock(&t4_uld_list_lock); return (rc); } int t4_deactivate_uld(struct adapter *sc, int id) { int rc; struct uld_info *ui; ASSERT_SYNCHRONIZED_OP(sc); if (id < 0 || id > ULD_MAX) return (EINVAL); rc = ENXIO; sx_slock(&t4_uld_list_lock); SLIST_FOREACH(ui, &t4_uld_list, link) { if (ui->uld_id == id) { rc = ui->deactivate(sc); if (rc == 0) { clrbit(&sc->active_ulds, id); ui->refcount--; } break; } } sx_sunlock(&t4_uld_list_lock); return (rc); } int uld_active(struct adapter *sc, int uld_id) { MPASS(uld_id >= 0 && uld_id <= ULD_MAX); return (isset(&sc->active_ulds, uld_id)); } #endif /* * t = ptr to tunable. * nc = number of CPUs. * c = compiled in default for that tunable. */ static void calculate_nqueues(int *t, int nc, const int c) { int nq; if (*t > 0) return; nq = *t < 0 ? -*t : c; *t = min(nc, nq); } /* * Come up with reasonable defaults for some of the tunables, provided they're * not set by the user (in which case we'll use the values as is). */ static void tweak_tunables(void) { int nc = mp_ncpus; /* our snapshot of the number of CPUs */ if (t4_ntxq10g < 1) { #ifdef RSS t4_ntxq10g = rss_getnumbuckets(); #else calculate_nqueues(&t4_ntxq10g, nc, NTXQ_10G); #endif } if (t4_ntxq1g < 1) { #ifdef RSS /* XXX: way too many for 1GbE? */ t4_ntxq1g = rss_getnumbuckets(); #else calculate_nqueues(&t4_ntxq1g, nc, NTXQ_1G); #endif } calculate_nqueues(&t4_ntxq_vi, nc, NTXQ_VI); if (t4_nrxq10g < 1) { #ifdef RSS t4_nrxq10g = rss_getnumbuckets(); #else calculate_nqueues(&t4_nrxq10g, nc, NRXQ_10G); #endif } if (t4_nrxq1g < 1) { #ifdef RSS /* XXX: way too many for 1GbE? */ t4_nrxq1g = rss_getnumbuckets(); #else calculate_nqueues(&t4_nrxq1g, nc, NRXQ_1G); #endif } calculate_nqueues(&t4_nrxq_vi, nc, NRXQ_VI); #ifdef TCP_OFFLOAD calculate_nqueues(&t4_nofldtxq10g, nc, NOFLDTXQ_10G); calculate_nqueues(&t4_nofldtxq1g, nc, NOFLDTXQ_1G); calculate_nqueues(&t4_nofldtxq_vi, nc, NOFLDTXQ_VI); calculate_nqueues(&t4_nofldrxq10g, nc, NOFLDRXQ_10G); calculate_nqueues(&t4_nofldrxq1g, nc, NOFLDRXQ_1G); calculate_nqueues(&t4_nofldrxq_vi, nc, NOFLDRXQ_VI); if (t4_toecaps_allowed == -1) t4_toecaps_allowed = FW_CAPS_CONFIG_TOE; if (t4_rdmacaps_allowed == -1) { t4_rdmacaps_allowed = FW_CAPS_CONFIG_RDMA_RDDP | FW_CAPS_CONFIG_RDMA_RDMAC; } if (t4_iscsicaps_allowed == -1) { t4_iscsicaps_allowed = FW_CAPS_CONFIG_ISCSI_INITIATOR_PDU | FW_CAPS_CONFIG_ISCSI_TARGET_PDU | FW_CAPS_CONFIG_ISCSI_T10DIF; } #else if (t4_toecaps_allowed == -1) t4_toecaps_allowed = 0; if (t4_rdmacaps_allowed == -1) t4_rdmacaps_allowed = 0; if (t4_iscsicaps_allowed == -1) t4_iscsicaps_allowed = 0; #endif #ifdef DEV_NETMAP calculate_nqueues(&t4_nnmtxq_vi, nc, NNMTXQ_VI); calculate_nqueues(&t4_nnmrxq_vi, nc, NNMRXQ_VI); #endif if (t4_tmr_idx_10g < 0 || t4_tmr_idx_10g >= SGE_NTIMERS) t4_tmr_idx_10g = TMR_IDX_10G; if (t4_pktc_idx_10g < -1 || t4_pktc_idx_10g >= SGE_NCOUNTERS) t4_pktc_idx_10g = PKTC_IDX_10G; if (t4_tmr_idx_1g < 0 || t4_tmr_idx_1g >= SGE_NTIMERS) t4_tmr_idx_1g = TMR_IDX_1G; if (t4_pktc_idx_1g < -1 || t4_pktc_idx_1g >= SGE_NCOUNTERS) t4_pktc_idx_1g = PKTC_IDX_1G; if (t4_qsize_txq < 128) t4_qsize_txq = 128; if (t4_qsize_rxq < 128) t4_qsize_rxq = 128; while (t4_qsize_rxq & 7) t4_qsize_rxq++; t4_intr_types &= INTR_MSIX | INTR_MSI | INTR_INTX; } #ifdef DDB static void t4_dump_tcb(struct adapter *sc, int tid) { uint32_t base, i, j, off, pf, reg, save, tcb_addr, win_pos; reg = PCIE_MEM_ACCESS_REG(A_PCIE_MEM_ACCESS_OFFSET, 2); save = t4_read_reg(sc, reg); base = sc->memwin[2].mw_base; /* Dump TCB for the tid */ tcb_addr = t4_read_reg(sc, A_TP_CMM_TCB_BASE); tcb_addr += tid * TCB_SIZE; if (is_t4(sc)) { pf = 0; win_pos = tcb_addr & ~0xf; /* start must be 16B aligned */ } else { pf = V_PFNUM(sc->pf); win_pos = tcb_addr & ~0x7f; /* start must be 128B aligned */ } t4_write_reg(sc, reg, win_pos | pf); t4_read_reg(sc, reg); off = tcb_addr - win_pos; for (i = 0; i < 4; i++) { uint32_t buf[8]; for (j = 0; j < 8; j++, off += 4) buf[j] = htonl(t4_read_reg(sc, base + off)); db_printf("%08x %08x %08x %08x %08x %08x %08x %08x\n", buf[0], buf[1], buf[2], buf[3], buf[4], buf[5], buf[6], buf[7]); } t4_write_reg(sc, reg, save); t4_read_reg(sc, reg); } static void t4_dump_devlog(struct adapter *sc) { struct devlog_params *dparams = &sc->params.devlog; struct fw_devlog_e e; int i, first, j, m, nentries, rc; uint64_t ftstamp = UINT64_MAX; if (dparams->start == 0) { db_printf("devlog params not valid\n"); return; } nentries = dparams->size / sizeof(struct fw_devlog_e); m = fwmtype_to_hwmtype(dparams->memtype); /* Find the first entry. */ first = -1; for (i = 0; i < nentries && !db_pager_quit; i++) { rc = -t4_mem_read(sc, m, dparams->start + i * sizeof(e), sizeof(e), (void *)&e); if (rc != 0) break; if (e.timestamp == 0) break; e.timestamp = be64toh(e.timestamp); if (e.timestamp < ftstamp) { ftstamp = e.timestamp; first = i; } } if (first == -1) return; i = first; do { rc = -t4_mem_read(sc, m, dparams->start + i * sizeof(e), sizeof(e), (void *)&e); if (rc != 0) return; if (e.timestamp == 0) return; e.timestamp = be64toh(e.timestamp); e.seqno = be32toh(e.seqno); for (j = 0; j < 8; j++) e.params[j] = be32toh(e.params[j]); db_printf("%10d %15ju %8s %8s ", e.seqno, e.timestamp, (e.level < nitems(devlog_level_strings) ? devlog_level_strings[e.level] : "UNKNOWN"), (e.facility < nitems(devlog_facility_strings) ? devlog_facility_strings[e.facility] : "UNKNOWN")); db_printf(e.fmt, e.params[0], e.params[1], e.params[2], e.params[3], e.params[4], e.params[5], e.params[6], e.params[7]); if (++i == nentries) i = 0; } while (i != first && !db_pager_quit); } static struct command_table db_t4_table = LIST_HEAD_INITIALIZER(db_t4_table); _DB_SET(_show, t4, NULL, db_show_table, 0, &db_t4_table); DB_FUNC(devlog, db_show_devlog, db_t4_table, CS_OWN, NULL) { device_t dev; int t; bool valid; valid = false; t = db_read_token(); if (t == tIDENT) { dev = device_lookup_by_name(db_tok_string); valid = true; } db_skip_to_eol(); if (!valid) { db_printf("usage: show t4 devlog \n"); return; } if (dev == NULL) { db_printf("device not found\n"); return; } t4_dump_devlog(device_get_softc(dev)); } DB_FUNC(tcb, db_show_t4tcb, db_t4_table, CS_OWN, NULL) { device_t dev; int radix, tid, t; bool valid; valid = false; radix = db_radix; db_radix = 10; t = db_read_token(); if (t == tIDENT) { dev = device_lookup_by_name(db_tok_string); t = db_read_token(); if (t == tNUMBER) { tid = db_tok_number; valid = true; } } db_radix = radix; db_skip_to_eol(); if (!valid) { db_printf("usage: show t4 tcb \n"); return; } if (dev == NULL) { db_printf("device not found\n"); return; } if (tid < 0) { db_printf("invalid tid\n"); return; } t4_dump_tcb(device_get_softc(dev), tid); } #endif static struct sx mlu; /* mod load unload */ SX_SYSINIT(cxgbe_mlu, &mlu, "cxgbe mod load/unload"); static int mod_event(module_t mod, int cmd, void *arg) { int rc = 0; static int loaded = 0; switch (cmd) { case MOD_LOAD: sx_xlock(&mlu); if (loaded++ == 0) { t4_sge_modload(); t4_register_cpl_handler(CPL_SET_TCB_RPL, set_tcb_rpl); t4_register_cpl_handler(CPL_L2T_WRITE_RPL, l2t_write_rpl); t4_register_cpl_handler(CPL_TRACE_PKT, t4_trace_pkt); t4_register_cpl_handler(CPL_T5_TRACE_PKT, t5_trace_pkt); sx_init(&t4_list_lock, "T4/T5 adapters"); SLIST_INIT(&t4_list); #ifdef TCP_OFFLOAD sx_init(&t4_uld_list_lock, "T4/T5 ULDs"); SLIST_INIT(&t4_uld_list); #endif t4_tracer_modload(); tweak_tunables(); } sx_xunlock(&mlu); break; case MOD_UNLOAD: sx_xlock(&mlu); if (--loaded == 0) { int tries; sx_slock(&t4_list_lock); if (!SLIST_EMPTY(&t4_list)) { rc = EBUSY; sx_sunlock(&t4_list_lock); goto done_unload; } #ifdef TCP_OFFLOAD sx_slock(&t4_uld_list_lock); if (!SLIST_EMPTY(&t4_uld_list)) { rc = EBUSY; sx_sunlock(&t4_uld_list_lock); sx_sunlock(&t4_list_lock); goto done_unload; } #endif tries = 0; while (tries++ < 5 && t4_sge_extfree_refs() != 0) { uprintf("%ju clusters with custom free routine " "still is use.\n", t4_sge_extfree_refs()); pause("t4unload", 2 * hz); } #ifdef TCP_OFFLOAD sx_sunlock(&t4_uld_list_lock); #endif sx_sunlock(&t4_list_lock); if (t4_sge_extfree_refs() == 0) { t4_tracer_modunload(); #ifdef TCP_OFFLOAD sx_destroy(&t4_uld_list_lock); #endif sx_destroy(&t4_list_lock); t4_sge_modunload(); loaded = 0; } else { rc = EBUSY; loaded++; /* undo earlier decrement */ } } done_unload: sx_xunlock(&mlu); break; } return (rc); } static devclass_t t4_devclass, t5_devclass, t6_devclass; static devclass_t cxgbe_devclass, cxl_devclass, cc_devclass; static devclass_t vcxgbe_devclass, vcxl_devclass, vcc_devclass; DRIVER_MODULE(t4nex, pci, t4_driver, t4_devclass, mod_event, 0); MODULE_VERSION(t4nex, 1); MODULE_DEPEND(t4nex, firmware, 1, 1, 1); #ifdef DEV_NETMAP MODULE_DEPEND(t4nex, netmap, 1, 1, 1); #endif /* DEV_NETMAP */ DRIVER_MODULE(t5nex, pci, t5_driver, t5_devclass, mod_event, 0); MODULE_VERSION(t5nex, 1); MODULE_DEPEND(t5nex, firmware, 1, 1, 1); #ifdef DEV_NETMAP MODULE_DEPEND(t5nex, netmap, 1, 1, 1); #endif /* DEV_NETMAP */ DRIVER_MODULE(t6nex, pci, t6_driver, t6_devclass, mod_event, 0); MODULE_VERSION(t6nex, 1); MODULE_DEPEND(t6nex, firmware, 1, 1, 1); #ifdef DEV_NETMAP MODULE_DEPEND(t6nex, netmap, 1, 1, 1); #endif /* DEV_NETMAP */ DRIVER_MODULE(cxgbe, t4nex, cxgbe_driver, cxgbe_devclass, 0, 0); MODULE_VERSION(cxgbe, 1); DRIVER_MODULE(cxl, t5nex, cxl_driver, cxl_devclass, 0, 0); MODULE_VERSION(cxl, 1); DRIVER_MODULE(cc, t6nex, cc_driver, cc_devclass, 0, 0); MODULE_VERSION(cc, 1); DRIVER_MODULE(vcxgbe, cxgbe, vcxgbe_driver, vcxgbe_devclass, 0, 0); MODULE_VERSION(vcxgbe, 1); DRIVER_MODULE(vcxl, cxl, vcxl_driver, vcxl_devclass, 0, 0); MODULE_VERSION(vcxl, 1); DRIVER_MODULE(vcc, cc, vcc_driver, vcc_devclass, 0, 0); MODULE_VERSION(vcc, 1); Index: projects/make-check-sandbox/sys/modules/cxgbe/if_cxgbe/Makefile =================================================================== --- projects/make-check-sandbox/sys/modules/cxgbe/if_cxgbe/Makefile (revision 322021) +++ projects/make-check-sandbox/sys/modules/cxgbe/if_cxgbe/Makefile (revision 322022) @@ -1,33 +1,39 @@ # # $FreeBSD$ # CXGBE= ${SRCTOP}/sys/dev/cxgbe -.PATH: ${CXGBE} ${CXGBE}/common +.PATH: ${CXGBE} ${CXGBE}/common ${CXGBE}/cudbg KMOD= if_cxgbe SRCS= bus_if.h SRCS+= device_if.h SRCS+= opt_ddb.h SRCS+= opt_inet.h SRCS+= opt_inet6.h SRCS+= opt_ofed.h SRCS+= opt_rss.h SRCS+= pci_if.h pci_iov_if.h SRCS+= t4_if.c t4_if.h SRCS+= t4_hw.c SRCS+= t4_iov.c SRCS+= t4_l2t.c SRCS+= t4_main.c SRCS+= t4_mp_ring.c SRCS+= t4_netmap.c SRCS+= t4_sched.c SRCS+= t4_sge.c SRCS+= t4_tracer.c +SRCS+= cudbg_common.c +SRCS+= cudbg_flash_utils.c +SRCS+= cudbg_lib.c +SRCS+= cudbg_wtp.c +SRCS+= fastlz_api.c +SRCS+= fastlz.c # Provide the timestamp of a packet in its header mbuf. #CFLAGS+= -DT4_PKT_TIMESTAMP CFLAGS+= -I${CXGBE} .include Index: projects/make-check-sandbox/usr.bin/cut/cut.1 =================================================================== --- projects/make-check-sandbox/usr.bin/cut/cut.1 (revision 322021) +++ projects/make-check-sandbox/usr.bin/cut/cut.1 (revision 322022) @@ -1,163 +1,167 @@ .\" Copyright (c) 1989, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" This code is derived from software contributed to Berkeley by .\" the Institute of Electrical and Electronics Engineers, Inc. .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)cut.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd August 8, 2012 +.Dd August 3, 2017 .Dt CUT 1 .Os .Sh NAME .Nm cut .Nd cut out selected portions of each line of a file .Sh SYNOPSIS .Nm .Fl b Ar list .Op Fl n .Op Ar .Nm .Fl c Ar list .Op Ar .Nm .Fl f Ar list .Op Fl w | Fl d Ar delim .Op Fl s .Op Ar .Sh DESCRIPTION The .Nm utility cuts out selected portions of each line (as specified by .Ar list ) from each .Ar file and writes them to the standard output. If no .Ar file arguments are specified, or a file argument is a single dash .Pq Sq Fl , .Nm reads from the standard input. The items specified by .Ar list can be in terms of column position or in terms of fields delimited by a special character. Column and field numbering start from 1. .Pp The .Ar list option argument is a comma or whitespace separated set of increasing numbers and/or number ranges. Number ranges consist of a number, a dash .Pq Sq \- , and a second number and select the columns or fields from the first number to the second, inclusive. Numbers or number ranges may be preceded by a dash, which selects all columns or fields from 1 to the last number. Numbers or number ranges may be followed by a dash, which selects all columns or fields from the last number to the end of the line. Numbers and number ranges may be repeated, overlapping, and in any order. It is not an error to select columns or fields not present in the input line. .Pp The options are as follows: .Bl -tag -width indent .It Fl b Ar list The .Ar list specifies byte positions. .It Fl c Ar list The .Ar list specifies character positions. .It Fl d Ar delim Use .Ar delim as the field delimiter character instead of the tab character. .It Fl f Ar list The .Ar list specifies fields, separated in the input by the field delimiter character (see the .Fl d option). Output fields are separated by a single occurrence of the field delimiter character. .It Fl n Do not split multi-byte characters. Characters will only be output if at least one byte is selected, and, after a prefix of zero or more unselected bytes, the rest of the bytes that form the character are selected. .It Fl s Suppress lines with no field delimiter characters. Unless specified, lines with no delimiters are passed through unmodified. .It Fl w Use whitespace (spaces and tabs) as the delimiter. Consecutive spaces and tabs count as one single field separator. .El .Sh ENVIRONMENT The .Ev LANG , LC_ALL and .Ev LC_CTYPE environment variables affect the execution of .Nm as described in .Xr environ 7 . .Sh EXIT STATUS .Ex -std .Sh EXAMPLES Extract users' login names and shells from the system .Xr passwd 5 file as .Dq name:shell pairs: .Pp .Dl "cut -d : -f 1,7 /etc/passwd" .Pp Show the names and login times of the currently logged in users: .Pp .Dl "who | cut -c 1-16,26-38" .Sh SEE ALSO .Xr colrm 1 , .Xr paste 1 .Sh STANDARDS The .Nm utility conforms to .St -p1003.2-92 . +.Pp +The +.Fl w +flag is an extension to the specification. .Sh HISTORY A .Nm command appeared in .Tn AT&T System III .Ux . Index: projects/make-check-sandbox/usr.bin/mt/mt.1 =================================================================== --- projects/make-check-sandbox/usr.bin/mt/mt.1 (revision 322021) +++ projects/make-check-sandbox/usr.bin/mt/mt.1 (revision 322022) @@ -1,632 +1,632 @@ .\" Copyright (c) 1981, 1990, 1993 .\" The Regents of the University of California. All rights reserved. .\" .\" .\" Redistribution and use in source and binary forms, with or without .\" modification, are permitted provided that the following conditions .\" are met: .\" 1. Redistributions of source code must retain the above copyright .\" notice, this list of conditions and the following disclaimer. .\" 2. Redistributions in binary form must reproduce the above copyright .\" notice, this list of conditions and the following disclaimer in the .\" documentation and/or other materials provided with the distribution. .\" 3. Neither the name of the University nor the names of its contributors .\" may be used to endorse or promote products derived from this software .\" without specific prior written permission. .\" .\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND .\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE .\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE .\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE .\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL .\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS .\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) .\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT .\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY .\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF .\" SUCH DAMAGE. .\" .\" @(#)mt.1 8.1 (Berkeley) 6/6/93 .\" $FreeBSD$ .\" -.Dd July 14, 2017 +.Dd August 3, 2017 .Dt MT 1 .Os .Sh NAME .Nm mt .Nd magnetic tape manipulating program .Sh SYNOPSIS .Nm .Op Fl f Ar tapename .Ar command .Op Ar count .Nm .Op Fl f Ar tapename .Ar command .Ar argument .Sh DESCRIPTION The .Nm utility is used to command a magnetic tape drive for operations other than reading or writing data. .Pp The .Fl f option's .Ar tapename overrides the .Ev TAPE environment variable described below. .Pp The available commands are listed below. Only as many characters as are required to uniquely identify a command need be specified. .Pp The following commands optionally take a .Ar count , which defaults to 1. .Bl -tag -width ".Cm erase" .It Cm weof Write .Ar count end-of-file (EOF) marks at the current position. This returns when the file mark has been written to the media. .It Cm weofi Write .Ar count end-of-file (EOF) marks at the current position. This returns as soon as the command has been validated by the tape drive. .It Cm smk Write .Ar count setmarks at the current position (DDS drives only). .It Cm fsf Forward space .Ar count files. .It Cm fsr Forward space .Ar count records. .It Cm fss Forward space .Ar count setmarks (DDS drives only). .It Cm bsf Backward space .Ar count files. .It Cm bsr Backward space .Ar count records. .It Cm bss Backward space .Ar count setmarks (DDS drives only). .It Cm erase Erase the tape using a long (often very long) method. With a .Ar count of 0, it will erase the tape using a quick method. Operation is not guaranteed if the tape is not at its beginning. The tape will be at its beginning upon completion. .El .Pp The following commands ignore .Ar count . .Bl -tag -width ".Cm geteotmodel" .It Cm rdhpos Read the hardware block position. The block number reported is specific for that hardware only. With drive data compression especially, this position may have more to do with the amount of data sent to the drive than the amount of data written to tape. Some drives do not support this. .It Cm rdspos Read the SCSI logical block position. This typically is greater than the hardware position by the number of end-of-file marks. Some drives do not support this. .It Cm rewind Rewind the tape. .It Cm offline , rewoffl Rewind the tape and place the drive off line. Some drives are never off line. .It Cm load Load the tape into the drive. .It Cm retension Re-tension the tape. This winds the tape from the current position to the end and then to the beginning. This sometimes improves subsequent reading and writing, particularly for streaming drives. Some drives do not support this. .It Cm ostatus Output status information about the drive. For SCSI magnetic tape devices, the current operating modes of density, blocksize, and whether compression is enabled is reported. The current state of the driver (what it thinks that it is doing with the device) is reported. If the driver knows the relative position from BOT (in terms of filemarks and records), it outputs that. Note that this information is not definitive (only BOT, End of Recorded Media, and hardware or SCSI logical block position (if the drive supports such) are considered definitive tape positions). .Pp Also note that this is the old status command, and will be eliminated in favor of the new status command (see below) in a future release. .It Cm errstat Output (and clear) error status information about this device. For every normal operation (e.g., a read or a write) and every control operation (e.g,, a rewind), the driver stores up the last command executed and it is associated status and any residual counts (if any). This command retrieves and outputs this information. If possible, this also clears any latched error information. .It Cm geteotmodel Output the current EOT filemark model. The model states how many filemarks will be written at close if a tape was being written. .It Cm eod , eom Wind the tape to the end of the recorded data, typically after an EOF mark where another file may be written. .It Cm rblim Report the block limits of the tape drive, including the minimum and maximum block size, and the block granularity if any. .El .Pp The following commands may require an .Ar argument . .Bl -tag -width ".Cm seteotmodel" .It Cm sethpos Set the hardware block position. The .Ar argument is a hardware block number to which to position the tape. Some drives do not support this. .It Cm setspos Set the SCSI logical block position. The .Ar argument is a SCSI logical block number to which to position the tape. Some drives do not support this. .It Cm blocksize Set the block size for the drive. The .Ar argument is the number of bytes per block, except 0 commands the drive to use variable-length blocks. .It Cm seteotmodel Set the EOT filemark model to .Ar argument and output the old and new models. Typically this will be 2 filemarks, but some devices (typically QIC cartridge drives) can only write 1 filemark. You may only choose a value of .Ar 1 or .Ar 2 . .It Cm status Output status information about the drive. For SCSI magnetic tape devices, the current operating modes of density, blocksize, and whether compression is enabled is reported. The current state of the driver (what it thinks that it is doing with the device) is reported. .Pp If the driver knows the relative position from BOT (in terms of filemarks and records), it outputs that. If the tape drive supports the long form report of the .Tn SCSI READ POSITION command, the Reported File Number and Reported Record Number will be numbers other than -1, and there may be Flags reported as well. .Pp The BOP flag means that the logical position of the drive is at the beginning of the partition. .Pp The EOP flag means that the logical position of the drive is between Early Warning and End of Partition. .Pp The BPEW flag means that the logical position of the drive is in a Programmable Early Warning Zone or on the EOP side of Early Warning. .Pp Note that the Reported Record Number is the tape block or object number relative to the beginning of the partition. The Calculated Record Number is the tape block or object number relative to the previous file mark. .Pp Note that the Calculated File and Record Numbers are not definitive. The Reported File and Record Numbers are definitive, if they are numbers other than -1. .Bl -tag -width 6n .It Fl v Print additional status information, such as the maximum supported I/O size. .It Fl x Print all available status data to stdout in XML format. .El .It Cm getdensity Report density support information for the tape drive and any media that is loaded. Most drives will report at least basic density information similar to that reported by .Nm status command. Newer tape drives that conform to the T-10 SSC and newer tape specifications may report more detailed information about the types of tapes they support and the tape currently in the drive. .Bl -tag -width 6n .It Fl x Print all available density data to stdout in XML format. Because density information is currently included in the general status XML report used for .Nm status command, this will be the same XML output via .Do .Nm status .Fl x .Dc .El .It Cm param Display or set parameters. One of .Fl l , .Fl s , or .Fl x must be specified to indicate which operation to perform. See .Xr sa 4 for more detailed information on the parameters. .Bl -tag -width 8n .It Fl l List parameters, values and descriptions. By default all parameters will be displayed. To display a specific parameter, specify the parameter with .Fl p . .It Fl p Ar name Specify the parameter name to list (with .Fl l ) or set (with .Fl s ) . .It Fl q Enable quiet mode for parameter listing. This will suppress printing of parameter descriptions. .It Fl s Ar value Specify the parameter value to set. The general type of this argument (integer, unsigned integer, string) is determined by the type of the variable indicated by the .Xr sa 4 driver. More detailed argument checking is done by the .Xr sa 4 driver. .It Fl x Print out all parameter information in XML format. .El .It Cm protect Display or set drive protection parameters. This is used to control checking and reporting a per-block checksum for tape drives that support it. Some drives may only support some parameters. .Bl -tag -width 8n .It Fl b Ar 0|1 Set the Recover Buffered Data Protected bit. If set, this indicates that checksums are transferred with the logical blocks transferred by the RECOVERED BUFFERED DATA .Tn SCSI command. .It Fl d Disable all protection information settings. .It Fl e Enable all protection information settings. The default protection method used is Reed-Solomon CRC (protection method 1), as specified in ECMA-319. The default protection information length used with Reed-Solomon CRC is 4 bytes. To enable all settings except one more more settings, specify the .Fl e argument and then explicitly disable settings that you do not wish to enable. For example, specifying .Fl e .Fl w Ar 0 will enable all settings except for LBP_W. .It Fl l List available protection parmeters and their current settings. .It Fl L Ar len Set the length of the protection information in bytes. For Reed-Solomon CRC, the protection information length should be 4 bytes. .It Fl m Ar num Specify the numeric value for the protection method. The numeric value for Reed-Solomon CRC is 1. .It Fl r Ar 0|1 Set the LBP_R parameter. When set, this indicates that each block read from the tape drive will have a checksum at the end. .It Fl v Enable verbose mode for parameter listing. This will include descriptions of each parameter. .It Fl w Ar 0|1 Set the LBP_W parameter. When set, this indicates that each block written to the tape drive will have a checksum at the end. The drive will verify the checksum before writing the block to tape. .El .It Cm locate Set the tape drive's logical position. One of .Fl b , .Fl e , .Fl f , or .Fl s must be specified to indicate the type of position. If the partition number is specified, the drive will first relocate to the given partition (if it exists) and then to the position indicated within that partition. If the partition number is not specified, the drive will relocate to the given position within the current partition. .Bl -tag -width 14n .It Fl b Ar block_addr Relocate to the given tape block or logical object identifier. Note that the block number is the Reported Record Number that is relative to the beginning of the partition (or beginning of tape). .It Fl e Relocate to the end of data. .It Fl f Ar fileno Relocate to the given file number. .It Fl p Ar partition Specify the partition to change to. .It Fl s Ar setmark Relocate to the given set mark. .El .It Cm comp Set the drive's compression mode. The non-numeric values of .Ar argument are: .Pp .Bl -tag -width 9n -compact .It off Turn compression off. .It on Turn compression on. .It none Same as .Ar off . .It enable Same as .Ar on . .It IDRC IBM Improved Data Recording Capability compression (0x10). .It DCLZ DCLZ compression algorithm (0x20). .El .Pp In addition to the above recognized compression keywords, the user can supply a numeric compression algorithm for the drive to use. In most cases, simply turning the compression .Sq on will have the desired effect of enabling the default compression algorithm supported by the drive. If this is not the case (see the .Cm status display to see which compression algorithm is currently in use), the user can manually specify one of the supported compression keywords (above), or supply a numeric compression value from the drive's specifications. .Pp Note that for some older tape drives (for example the Exabyte 8200 and 8500 series drives) it is necessary to switch to a different density to tell the drive to record data in its compressed format. If the user attempts to turn compression on while the uncompressed density is selected, the drive will return an error. This is generally not an issue for modern tape drives. .It Cm density Set the density for the drive. For the density codes, see below. The density value could be given either numerically, or as a string, corresponding to the .Dq Reference field. If the string is abbreviated, it will be resolved in the order shown in the table, and the first matching entry will be used. If the given string and the resulting canonical density name do not match exactly, an informational message is output about what the given string has been taken for. .El .Pp The initial version of the density table below was taken from the .Sq Historical sequential access density codes table (A-1) in Revision 11 of the SCSI-3 Stream Device Commands (SSC) working draft, dated November 11, 1997. Subsequent additions have come from a number of sources. .Pp The density codes are: .Bd -literal -offset 2n 0x0 default for device 0xE reserved for ECMA Value Width Tracks Density Code Type Reference Note mm in bpmm bpi 0x01 12.7 (0.5) 9 32 (800) NRZI R X3.22-1983 2 0x02 12.7 (0.5) 9 63 (1,600) PE R X3.39-1986 2 0x03 12.7 (0.5) 9 246 (6,250) GCR R X3.54-1986 2 0x05 6.3 (0.25) 4/9 315 (8,000) GCR C X3.136-1986 1 0x06 12.7 (0.5) 9 126 (3,200) PE R X3.157-1987 2 0x07 6.3 (0.25) 4 252 (6,400) IMFM C X3.116-1986 1 0x08 3.81 (0.15) 4 315 (8,000) GCR CS X3.158-1987 1 0x09 12.7 (0.5) 18 1,491 (37,871) GCR C X3.180 2 0x0A 12.7 (0.5) 22 262 (6,667) MFM C X3B5/86-199 1 0x0B 6.3 (0.25) 4 63 (1,600) PE C X3.56-1986 1 0x0C 12.7 (0.5) 24 500 (12,690) GCR C HI-TC1 1,6 0x0D 12.7 (0.5) 24 999 (25,380) GCR C HI-TC2 1,6 0x0F 6.3 (0.25) 15 394 (10,000) GCR C QIC-120 1,6 0x10 6.3 (0.25) 18 394 (10,000) GCR C QIC-150 1,6 0x11 6.3 (0.25) 26 630 (16,000) GCR C QIC-320 1,6 0x12 6.3 (0.25) 30 2,034 (51,667) RLL C QIC-1350 1,6 0x13 3.81 (0.15) 1 2,400 (61,000) DDS CS X3B5/88-185A 5 0x14 8.0 (0.315) 1 1,703 (43,245) RLL CS X3.202-1991 5,11 0x15 8.0 (0.315) 1 1,789 (45,434) RLL CS ECMA TC17 5,12 0x16 12.7 (0.5) 48 394 (10,000) MFM C X3.193-1990 1 0x17 12.7 (0.5) 48 1,673 (42,500) MFM C X3B5/91-174 1 0x18 12.7 (0.5) 112 1,673 (42,500) MFM C X3B5/92-50 1 0x19 12.7 (0.5) 128 2,460 (62,500) RLL C DLTapeIII 6,7 0x1A 12.7 (0.5) 128 3,214 (81,633) RLL C DLTapeIV(20) 6,7 0x1B 12.7 (0.5) 208 3,383 (85,937) RLL C DLTapeIV(35) 6,7 0x1C 6.3 (0.25) 34 1,654 (42,000) MFM C QIC-385M 1,6 0x1D 6.3 (0.25) 32 1,512 (38,400) GCR C QIC-410M 1,6 0x1E 6.3 (0.25) 30 1,385 (36,000) GCR C QIC-1000C 1,6 0x1F 6.3 (0.25) 30 2,666 (67,733) RLL C QIC-2100C 1,6 0x20 6.3 (0.25) 144 2,666 (67,733) RLL C QIC-6GB(M) 1,6 0x21 6.3 (0.25) 144 2,666 (67,733) RLL C QIC-20GB(C) 1,6 0x22 6.3 (0.25) 42 1,600 (40,640) GCR C QIC-2GB(C) ? 0x23 6.3 (0.25) 38 2,666 (67,733) RLL C QIC-875M ? 0x24 3.81 (0.15) 1 2,400 (61,000) CS DDS-2 5 0x25 3.81 (0.15) 1 3,816 (97,000) CS DDS-3 5 0x26 3.81 (0.15) 1 3,816 (97,000) CS DDS-4 5 0x27 8.0 (0.315) 1 3,056 (77,611) RLL CS Mammoth 5 0x28 12.7 (0.5) 36 1,491 (37,871) GCR C X3.224 1 0x29 12.7 (0.5) 0x2A 0x2B 12.7 (0.5) 3 ? ? ? C X3.267 5 0x40 12.7 (0.5) 384 4,800 (123,952) C LTO-1 0x41 12.7 (0.5) 208 3,868 (98,250) RLL C DLTapeIV(40) 6,7 0x42 12.7 (0.5) 512 7,398 (187,909) C LTO-2 0x44 12.7 (0.5) 704 9,638 (244,805) C LTO-3 0x46 12.7 (0.5) 896 12,725 (323,215) C LTO-4 0x47 3.81 (0.25) ? 6,417 (163,000) CS DAT-72 0x48 12.7 (0.5) 448 5,236 (133,000) PRML C SDLTapeI(110) 6,8,13 0x49 12.7 (0.5) 448 7,598 (193,000) PRML C SDLTapeI(160) 6,8 -0x4A 12.7 (0.5) 768 ? C T10000A 10 -0x4B 12.7 (0.5) 1152 ? C T10000B 10 -0x4C 12.7 (0.5) 3584 ? C T10000C 10 -0x4D 12.7 (0.5) 4608 ? C T10000D 10 +0x4A 12.7 (0.5) 768 ? PRML C T10000A 10 +0x4B 12.7 (0.5) 1152 ? PRML C T10000B 10 +0x4C 12.7 (0.5) 3584 ? PRML C T10000C 10 +0x4D 12.7 (0.5) 4608 ? PRML C T10000D 10 0x51 12.7 (0.5) 512 11,800 (299,720) C 3592A1 (unencrypted) 0x52 12.7 (0.5) 896 11,800 (299,720) C 3592A2 (unencrypted) 0x53 12.7 (0.5) 1152 13,452 (341,681) C 3592A3 (unencrypted) 0x54 12.7 (0.5) 2560 19,686 (500,024) C 3592A4 (unencrypted) 0x55 12.7 (0.5) 5120 20,670 (525,018) C 3592A5 (unencrypted) 0x56 12.7 (0.5) 7680 20,670 (525,018) C 3592B5 (unencrypted) 0x58 12.7 (0.5) 1280 15,142 (384,607) C LTO-5 0x5A 12.7 (0.5) 2176 15,142 (384,607) C LTO-6 0x5C 12.7 (0.5) 3584 19,107 (485,318) C LTO-7 0x5E 12.7 (0.5) 6656 20,669 (524,993) C LTO-8 0x71 12.7 (0.5) 512 11,800 (299,720) C 3592A1 (encrypted) 0x72 12.7 (0.5) 896 11,800 (299,720) C 3592A2 (encrypted) 0x73 12.7 (0.5) 1152 13,452 (341,681) C 3592A3 (encrypted) 0x74 12.7 (0.5) 2560 19,686 (500,024) C 3592A4 (encrypted) 0x75 12.7 (0.5) 5120 20,670 (525,018) C 3592A5 (encrypted) 0x76 12.7 (0.5) 7680 20,670 (525,018) C 3592B5 (encrypted) 0x8c 8.0 (0.315) 1 1,789 (45,434) RLL CS EXB-8500c 5,9 0x90 8.0 (0.315) 1 1,703 (43,245) RLL CS EXB-8200c 5,9 .Ed .Bd -literal -offset 2n Code Description Type Description ---- -------------------------------------- ---- ----------- NRZI Non return to zero, change on ones R Reel-to-reel GCR Group code recording C Cartridge PE Phase encoded CS Cassette IMFM Inverted modified frequency modulation MFM Modified frequency modulation DDS DAT data storage RLL Run length limited PRML Partial Response Maximum Likelihood .Ed .Bd -literal -offset 2n NOTES 1. Serial recorded. 2. Parallel recorded. 3. Old format known as QIC-11. 5. Helical scan. 6. This is not an American National Standard. The reference is based on an industry standard definition of the media format. 7. DLT recording: serially recorded track pairs (DLTapeIII and DLTapeIV(20)), or track quads (DLTapeIV(35) and DLTapeIV(40)). 8. Super DLT (SDLT) recording: 56 serially recorded logical tracks with 8 physical tracks each. 9. Vendor-specific Exabyte density code for compressed format. 10. bpi/bpmm values for the Oracle/StorageTek T10000 tape drives are not listed in the manual. Someone with access to a drive can supply the necessary values by running 'mt getdensity'. 11. This is Exabyte 8200 uncompressed format. The compressed format density code is 0x90. 12. This is Exabyte 8500 uncompressed format. The compressed format density code is 0x8c. 13. This density code (0x48) was also used for DAT-160. .Ed .Sh ENVIRONMENT .Bl -tag -width ".Ev TAPE" .It Ev TAPE This is the pathname of the tape drive. The default (if the variable is unset, but not if it is null) is .Pa /dev/nsa0 . It may be overridden with the .Fl f option. .El .Sh FILES .Bl -tag -width ".Pa /dev/*sa[0-9]*" -compact .It Pa /dev/*sa[0-9]* SCSI magnetic tape interface .El .Sh DIAGNOSTICS The exit status will be 0 when the drive operations were successful, 2 when the drive operations were unsuccessful, and 1 for other problems like an unrecognized command or a missing drive device. .Sh COMPATIBILITY Some undocumented commands support old software. .Sh SEE ALSO .Xr dd 1 , .Xr ioctl 2 , .Xr mtio 4 , .Xr sa 4 , .Xr environ 7 .Sh HISTORY The .Nm command appeared in .Bx 4.3 . .Pp Extensions regarding the .Xr st 4 driver appeared in .Bx 386 0.1 as a separate .Nm st command, and have been merged into the .Nm command in .Fx 2.1 . .Pp The former .Cm eof command that used to be a synonym for .Cm weof has been abandoned in .Fx 2.1 since it was often confused with .Cm eom , which is fairly dangerous. .Sh BUGS The utility cannot be interrupted or killed during a long erase (which can be longer than an hour), and it is easy to forget that the default erase is long. .Pp Hardware block numbers do not always correspond to blocks on the tape when the drive uses internal compression. .Pp Erasure is not guaranteed if the tape is not at its beginning. .Pp Tape-related documentation is poor, here and elsewhere. Index: projects/make-check-sandbox/usr.bin/xohtml/xohtml.sh =================================================================== --- projects/make-check-sandbox/usr.bin/xohtml/xohtml.sh (revision 322021) +++ projects/make-check-sandbox/usr.bin/xohtml/xohtml.sh (revision 322022) @@ -1,79 +1,87 @@ #!/bin/sh # $FreeBSD$ +#!/bin/sh # # Copyright (c) 2014, Juniper Networks, Inc. # All rights reserved. # This SOFTWARE is licensed under the LICENSE provided in the # ../Copyright file. By downloading, installing, copying, or otherwise # using the SOFTWARE, you agree to be bound by the terms of that # LICENSE. # Phil Shafer, July 2014 # BASE=/usr/share/libxo +VERSION=0.8.4 CMD=cat DONE= +WEB=http://juniper.github.io/libxo/${VERSION}/xohtml do_help () { echo "xohtml: wrap libxo-enabled output in HTML" echo "Usage: xohtml [options] [command [arguments]]" echo "Valid options are:" echo " -b | --base " echo " -c | --command " echo " -f | --file " exit 1 } while [ -z "$DONE" -a ! -z "$1" ]; do case "$1" in -b|--base) shift; BASE="$1"; shift; ;; -c|--command) shift; CMD="$1"; shift; ;; -f|--file) shift; FILE="$1"; shift; exec > "$FILE"; ;; + -w|--web) + shift; + BASE="${WEB}"; + ;; + -*) do_help ;; *) DONE=1; XX=$1; shift; CMD="$XX --libxo=html $@" ;; esac done if [ "$CMD" = "cat" -a -t 0 ]; then do_help fi echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' echo '' $CMD echo '' echo '' exit 0 Index: projects/make-check-sandbox/usr.sbin/cxgbetool/cxgbetool.c =================================================================== --- projects/make-check-sandbox/usr.sbin/cxgbetool/cxgbetool.c (revision 322021) +++ projects/make-check-sandbox/usr.sbin/cxgbetool/cxgbetool.c (revision 322022) @@ -1,2975 +1,3012 @@ /*- * Copyright (c) 2011 Chelsio Communications, Inc. * All rights reserved. * Written by: Navdeep Parhar * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */ #include __FBSDID("$FreeBSD$"); #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include "t4_ioctl.h" #define in_range(val, lo, hi) ( val < 0 || (val <= hi && val >= lo)) #define max(x, y) ((x) > (y) ? (x) : (y)) static const char *progname, *nexus; static int chip_id; /* 4 for T4, 5 for T5 */ struct reg_info { const char *name; uint32_t addr; uint32_t len; }; struct mod_regs { const char *name; const struct reg_info *ri; }; struct field_desc { const char *name; /* Field name */ unsigned short start; /* Start bit position */ unsigned short end; /* End bit position */ unsigned char shift; /* # of low order bits omitted and implicitly 0 */ unsigned char hex; /* Print field in hex instead of decimal */ unsigned char islog2; /* Field contains the base-2 log of the value */ }; #include "reg_defs_t4.c" #include "reg_defs_t5.c" #include "reg_defs_t6.c" #include "reg_defs_t4vf.c" static void usage(FILE *fp) { fprintf(fp, "Usage: %s [operation]\n", progname); fprintf(fp, "\tclearstats clear port statistics\n" "\tcontext show an SGE context\n" + "\tdumpstate dump chip state\n" "\tfilter [ ] ... set a filter\n" "\tfilter delete|clear delete a filter\n" "\tfilter list list all filters\n" "\tfilter mode [] ... get/set global filter mode\n" "\ti2c [] read from i2c device\n" "\tloadboot [pf|offset ] install boot image\n" "\tloadboot clear [pf|offset ] remove boot image\n" "\tloadboot-cfg install boot config\n" "\tloadboot-cfg clear remove boot config\n" "\tloadcfg install configuration file\n" "\tloadcfg clear remove configuration file\n" "\tloadfw install firmware\n" "\tmemdump dump a memory range\n" "\tmodinfo [raw] optics/cable information\n" "\treg
[=] read/write register\n" "\treg64
[=] read/write 64 bit register\n" "\tregdump [] ... dump registers\n" "\tsched-class params .. configure TX scheduler class\n" "\tsched-queue bind NIC queues to TX Scheduling class\n" "\tstdio interactive mode\n" "\ttcb read TCB\n" "\ttracer tx|rx set and enable a tracer\n" "\ttracer disable|enable disable or enable a tracer\n" "\ttracer list list all tracers\n" ); } static inline unsigned int get_card_vers(unsigned int version) { return (version & 0x3ff); } static int real_doit(unsigned long cmd, void *data, const char *cmdstr) { static int fd = -1; int rc = 0; if (fd == -1) { char buf[64]; snprintf(buf, sizeof(buf), "/dev/%s", nexus); if ((fd = open(buf, O_RDWR)) < 0) { warn("open(%s)", nexus); rc = errno; return (rc); } chip_id = nexus[1] - '0'; } rc = ioctl(fd, cmd, data); if (rc < 0) { warn("%s", cmdstr); rc = errno; } return (rc); } #define doit(x, y) real_doit(x, y, #x) static char * str_to_number(const char *s, long *val, long long *vall) { char *p; if (vall) *vall = strtoll(s, &p, 0); else if (val) *val = strtol(s, &p, 0); else p = NULL; return (p); } static int read_reg(long addr, int size, long long *val) { struct t4_reg reg; int rc; reg.addr = (uint32_t) addr; reg.size = (uint32_t) size; reg.val = 0; rc = doit(CHELSIO_T4_GETREG, ®); *val = reg.val; return (rc); } static int write_reg(long addr, int size, long long val) { struct t4_reg reg; reg.addr = (uint32_t) addr; reg.size = (uint32_t) size; reg.val = (uint64_t) val; return doit(CHELSIO_T4_SETREG, ®); } static int register_io(int argc, const char *argv[], int size) { char *p, *v; long addr; long long val; int w = 0, rc; if (argc == 1) { /* OR = */ p = str_to_number(argv[0], &addr, NULL); if (*p) { if (*p != '=') { warnx("invalid register \"%s\"", argv[0]); return (EINVAL); } w = 1; v = p + 1; p = str_to_number(v, NULL, &val); if (*p) { warnx("invalid value \"%s\"", v); return (EINVAL); } } } else if (argc == 2) { /* */ w = 1; p = str_to_number(argv[0], &addr, NULL); if (*p) { warnx("invalid register \"%s\"", argv[0]); return (EINVAL); } p = str_to_number(argv[1], NULL, &val); if (*p) { warnx("invalid value \"%s\"", argv[1]); return (EINVAL); } } else { warnx("reg: invalid number of arguments (%d)", argc); return (EINVAL); } if (w) rc = write_reg(addr, size, val); else { rc = read_reg(addr, size, &val); if (rc == 0) printf("0x%llx [%llu]\n", val, val); } return (rc); } static inline uint32_t xtract(uint32_t val, int shift, int len) { return (val >> shift) & ((1 << len) - 1); } static int dump_block_regs(const struct reg_info *reg_array, const uint32_t *regs) { uint32_t reg_val = 0; for ( ; reg_array->name; ++reg_array) if (!reg_array->len) { reg_val = regs[reg_array->addr / 4]; printf("[%#7x] %-47s %#-10x %u\n", reg_array->addr, reg_array->name, reg_val, reg_val); } else { uint32_t v = xtract(reg_val, reg_array->addr, reg_array->len); printf(" %*u:%u %-47s %#-10x %u\n", reg_array->addr < 10 ? 3 : 2, reg_array->addr + reg_array->len - 1, reg_array->addr, reg_array->name, v, v); } return (1); } static int dump_regs_table(int argc, const char *argv[], const uint32_t *regs, const struct mod_regs *modtab, int nmodules) { int i, j, match; for (i = 0; i < argc; i++) { for (j = 0; j < nmodules; j++) { if (!strcmp(argv[i], modtab[j].name)) break; } if (j == nmodules) { warnx("invalid register block \"%s\"", argv[i]); fprintf(stderr, "\nAvailable blocks:"); for ( ; nmodules; nmodules--, modtab++) fprintf(stderr, " %s", modtab->name); fprintf(stderr, "\n"); return (EINVAL); } } for ( ; nmodules; nmodules--, modtab++) { match = argc == 0 ? 1 : 0; for (i = 0; !match && i < argc; i++) { if (!strcmp(argv[i], modtab->name)) match = 1; } if (match) dump_block_regs(modtab->ri, regs); } return (0); } #define T4_MODREGS(name) { #name, t4_##name##_regs } static int dump_regs_t4(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t4_mod[] = { T4_MODREGS(sge), { "pci", t4_pcie_regs }, T4_MODREGS(dbg), T4_MODREGS(mc), T4_MODREGS(ma), { "edc0", t4_edc_0_regs }, { "edc1", t4_edc_1_regs }, T4_MODREGS(cim), T4_MODREGS(tp), T4_MODREGS(ulp_rx), T4_MODREGS(ulp_tx), { "pmrx", t4_pm_rx_regs }, { "pmtx", t4_pm_tx_regs }, T4_MODREGS(mps), { "cplsw", t4_cpl_switch_regs }, T4_MODREGS(smb), { "i2c", t4_i2cm_regs }, T4_MODREGS(mi), T4_MODREGS(uart), T4_MODREGS(pmu), T4_MODREGS(sf), T4_MODREGS(pl), T4_MODREGS(le), T4_MODREGS(ncsi), T4_MODREGS(xgmac) }; return dump_regs_table(argc, argv, regs, t4_mod, nitems(t4_mod)); } #undef T4_MODREGS #define T5_MODREGS(name) { #name, t5_##name##_regs } static int dump_regs_t5(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t5_mod[] = { T5_MODREGS(sge), { "pci", t5_pcie_regs }, T5_MODREGS(dbg), { "mc0", t5_mc_0_regs }, { "mc1", t5_mc_1_regs }, T5_MODREGS(ma), { "edc0", t5_edc_t50_regs }, { "edc1", t5_edc_t51_regs }, T5_MODREGS(cim), T5_MODREGS(tp), { "ulprx", t5_ulp_rx_regs }, { "ulptx", t5_ulp_tx_regs }, { "pmrx", t5_pm_rx_regs }, { "pmtx", t5_pm_tx_regs }, T5_MODREGS(mps), { "cplsw", t5_cpl_switch_regs }, T5_MODREGS(smb), { "i2c", t5_i2cm_regs }, T5_MODREGS(mi), T5_MODREGS(uart), T5_MODREGS(pmu), T5_MODREGS(sf), T5_MODREGS(pl), T5_MODREGS(le), T5_MODREGS(ncsi), T5_MODREGS(mac), { "hma", t5_hma_t5_regs } }; return dump_regs_table(argc, argv, regs, t5_mod, nitems(t5_mod)); } #undef T5_MODREGS #define T6_MODREGS(name) { #name, t6_##name##_regs } static int dump_regs_t6(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t6_mod[] = { T6_MODREGS(sge), { "pci", t6_pcie_regs }, T6_MODREGS(dbg), { "mc0", t6_mc_0_regs }, T6_MODREGS(ma), { "edc0", t6_edc_t60_regs }, { "edc1", t6_edc_t61_regs }, T6_MODREGS(cim), T6_MODREGS(tp), { "ulprx", t6_ulp_rx_regs }, { "ulptx", t6_ulp_tx_regs }, { "pmrx", t6_pm_rx_regs }, { "pmtx", t6_pm_tx_regs }, T6_MODREGS(mps), { "cplsw", t6_cpl_switch_regs }, T6_MODREGS(smb), { "i2c", t6_i2cm_regs }, T6_MODREGS(mi), T6_MODREGS(uart), T6_MODREGS(pmu), T6_MODREGS(sf), T6_MODREGS(pl), T6_MODREGS(le), T6_MODREGS(ncsi), T6_MODREGS(mac), { "hma", t6_hma_t6_regs } }; return dump_regs_table(argc, argv, regs, t6_mod, nitems(t6_mod)); } #undef T6_MODREGS static int dump_regs_t4vf(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t4vf_mod[] = { { "sge", t4vf_sge_regs }, { "mps", t4vf_mps_regs }, { "pl", t4vf_pl_regs }, { "mbdata", t4vf_mbdata_regs }, { "cim", t4vf_cim_regs }, }; return dump_regs_table(argc, argv, regs, t4vf_mod, nitems(t4vf_mod)); } static int dump_regs_t5vf(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t5vf_mod[] = { { "sge", t5vf_sge_regs }, { "mps", t4vf_mps_regs }, { "pl", t5vf_pl_regs }, { "mbdata", t4vf_mbdata_regs }, { "cim", t4vf_cim_regs }, }; return dump_regs_table(argc, argv, regs, t5vf_mod, nitems(t5vf_mod)); } static int dump_regs_t6vf(int argc, const char *argv[], const uint32_t *regs) { static struct mod_regs t6vf_mod[] = { { "sge", t5vf_sge_regs }, { "mps", t4vf_mps_regs }, { "pl", t6vf_pl_regs }, { "mbdata", t4vf_mbdata_regs }, { "cim", t4vf_cim_regs }, }; return dump_regs_table(argc, argv, regs, t6vf_mod, nitems(t6vf_mod)); } static int dump_regs(int argc, const char *argv[]) { int vers, revision, rc; struct t4_regdump regs; uint32_t len; len = max(T4_REGDUMP_SIZE, T5_REGDUMP_SIZE); regs.data = calloc(1, len); if (regs.data == NULL) { warnc(ENOMEM, "regdump"); return (ENOMEM); } regs.len = len; rc = doit(CHELSIO_T4_REGDUMP, ®s); if (rc != 0) return (rc); vers = get_card_vers(regs.version); revision = (regs.version >> 10) & 0x3f; if (vers == 4) { if (revision == 0x3f) rc = dump_regs_t4vf(argc, argv, regs.data); else rc = dump_regs_t4(argc, argv, regs.data); } else if (vers == 5) { if (revision == 0x3f) rc = dump_regs_t5vf(argc, argv, regs.data); else rc = dump_regs_t5(argc, argv, regs.data); } else if (vers == 6) { if (revision == 0x3f) rc = dump_regs_t6vf(argc, argv, regs.data); else rc = dump_regs_t6(argc, argv, regs.data); } else { warnx("%s (type %d, rev %d) is not a known card.", nexus, vers, revision); return (ENOTSUP); } free(regs.data); return (rc); } static void do_show_info_header(uint32_t mode) { uint32_t i; printf("%4s %8s", "Idx", "Hits"); for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { switch (mode & i) { case T4_FILTER_FCoE: printf(" FCoE"); break; case T4_FILTER_PORT: printf(" Port"); break; case T4_FILTER_VNIC: if (mode & T4_FILTER_IC_VNIC) printf(" VFvld:PF:VF"); else printf(" vld:oVLAN"); break; case T4_FILTER_VLAN: printf(" vld:VLAN"); break; case T4_FILTER_IP_TOS: printf(" TOS"); break; case T4_FILTER_IP_PROTO: printf(" Prot"); break; case T4_FILTER_ETH_TYPE: printf(" EthType"); break; case T4_FILTER_MAC_IDX: printf(" MACIdx"); break; case T4_FILTER_MPS_HIT_TYPE: printf(" MPS"); break; case T4_FILTER_IP_FRAGMENT: printf(" Frag"); break; default: /* compressed filter field not enabled */ break; } } printf(" %20s %20s %9s %9s %s\n", "DIP", "SIP", "DPORT", "SPORT", "Action"); } /* * Parse an argument sub-vector as a { [:] } * ordered tuple. If the parameter name in the argument sub-vector does not * match the passed in parameter name, then a zero is returned for the * function and no parsing is performed. If there is a match, then the value * and optional mask are parsed and returned in the provided return value * pointers. If no optional mask is specified, then a default mask of all 1s * will be returned. * * An error in parsing the value[:mask] will result in an error message and * program termination. */ static int parse_val_mask(const char *param, const char *args[], uint32_t *val, uint32_t *mask) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); *val = strtoul(args[1], &p, 0); if (p > args[1]) { if (p[0] == 0) { *mask = ~0; return (0); } if (p[0] == ':' && p[1] != 0) { *mask = strtoul(p+1, &p, 0); if (p[0] == 0) return (0); } } warnx("parameter \"%s\" has bad \"value[:mask]\" %s", args[0], args[1]); return (EINVAL); } /* * Parse an argument sub-vector as a { [/] } * ordered tuple. If the parameter name in the argument sub-vector does not * match the passed in parameter name, then a zero is returned for the * function and no parsing is performed. If there is a match, then the value * and optional mask are parsed and returned in the provided return value * pointers. If no optional mask is specified, then a default mask of all 1s * will be returned. * * The value return parameter "afp" is used to specify the expected address * family -- IPv4 or IPv6 -- of the address[/mask] and return its actual * format. A passed in value of AF_UNSPEC indicates that either IPv4 or IPv6 * is acceptable; AF_INET means that only IPv4 addresses are acceptable; and * AF_INET6 means that only IPv6 are acceptable. AF_INET is returned for IPv4 * and AF_INET6 for IPv6 addresses, respectively. IPv4 address/mask pairs are * returned in the first four bytes of the address and mask return values with * the address A.B.C.D returned with { A, B, C, D } returned in addresses { 0, * 1, 2, 3}, respectively. * * An error in parsing the value[:mask] will result in an error message and * program termination. */ static int parse_ipaddr(const char *param, const char *args[], int *afp, uint8_t addr[], uint8_t mask[]) { const char *colon, *afn; char *slash; uint8_t *m; int af, ret; unsigned int masksize; /* * Is this our parameter? */ if (strcmp(param, args[0]) != 0) return (EINVAL); /* * Fundamental IPv4 versus IPv6 selection. */ colon = strchr(args[1], ':'); if (!colon) { afn = "IPv4"; af = AF_INET; masksize = 32; } else { afn = "IPv6"; af = AF_INET6; masksize = 128; } if (*afp == AF_UNSPEC) *afp = af; else if (*afp != af) { warnx("address %s is not of expected family %s", args[1], *afp == AF_INET ? "IP" : "IPv6"); return (EINVAL); } /* * Parse address (temporarily stripping off any "/mask" * specification). */ slash = strchr(args[1], '/'); if (slash) *slash = 0; ret = inet_pton(af, args[1], addr); if (slash) *slash = '/'; if (ret <= 0) { warnx("Cannot parse %s %s address %s", param, afn, args[1]); return (EINVAL); } /* * Parse optional mask specification. */ if (slash) { char *p; unsigned int prefix = strtoul(slash + 1, &p, 10); if (p == slash + 1) { warnx("missing address prefix for %s", param); return (EINVAL); } if (*p) { warnx("%s is not a valid address prefix", slash + 1); return (EINVAL); } if (prefix > masksize) { warnx("prefix %u is too long for an %s address", prefix, afn); return (EINVAL); } memset(mask, 0, masksize / 8); masksize = prefix; } /* * Fill in mask. */ for (m = mask; masksize >= 8; m++, masksize -= 8) *m = ~0; if (masksize) *m = ~0 << (8 - masksize); return (0); } /* * Parse an argument sub-vector as a { } ordered * tuple. If the parameter name in the argument sub-vector does not match the * passed in parameter name, then a zero is returned for the function and no * parsing is performed. If there is a match, then the value is parsed and * returned in the provided return value pointer. */ static int parse_val(const char *param, const char *args[], uint32_t *val) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); *val = strtoul(args[1], &p, 0); if (p > args[1] && p[0] == 0) return (0); warnx("parameter \"%s\" has bad \"value\" %s", args[0], args[1]); return (EINVAL); } static void filters_show_ipaddr(int type, uint8_t *addr, uint8_t *addrm) { int noctets, octet; printf(" "); if (type == 0) { noctets = 4; printf("%3s", " "); } else noctets = 16; for (octet = 0; octet < noctets; octet++) printf("%02x", addr[octet]); printf("/"); for (octet = 0; octet < noctets; octet++) printf("%02x", addrm[octet]); } static void do_show_one_filter_info(struct t4_filter *t, uint32_t mode) { uint32_t i; printf("%4d", t->idx); if (t->hits == UINT64_MAX) printf(" %8s", "-"); else printf(" %8ju", t->hits); /* * Compressed header portion of filter. */ for (i = T4_FILTER_FCoE; i <= T4_FILTER_IP_FRAGMENT; i <<= 1) { switch (mode & i) { case T4_FILTER_FCoE: printf(" %1d/%1d", t->fs.val.fcoe, t->fs.mask.fcoe); break; case T4_FILTER_PORT: printf(" %1d/%1d", t->fs.val.iport, t->fs.mask.iport); break; case T4_FILTER_VNIC: if (mode & T4_FILTER_IC_VNIC) { printf(" %1d:%1x:%02x/%1d:%1x:%02x", t->fs.val.pfvf_vld, (t->fs.val.vnic >> 13) & 0x7, t->fs.val.vnic & 0x1fff, t->fs.mask.pfvf_vld, (t->fs.mask.vnic >> 13) & 0x7, t->fs.mask.vnic & 0x1fff); } else { printf(" %1d:%04x/%1d:%04x", t->fs.val.ovlan_vld, t->fs.val.vnic, t->fs.mask.ovlan_vld, t->fs.mask.vnic); } break; case T4_FILTER_VLAN: printf(" %1d:%04x/%1d:%04x", t->fs.val.vlan_vld, t->fs.val.vlan, t->fs.mask.vlan_vld, t->fs.mask.vlan); break; case T4_FILTER_IP_TOS: printf(" %02x/%02x", t->fs.val.tos, t->fs.mask.tos); break; case T4_FILTER_IP_PROTO: printf(" %02x/%02x", t->fs.val.proto, t->fs.mask.proto); break; case T4_FILTER_ETH_TYPE: printf(" %04x/%04x", t->fs.val.ethtype, t->fs.mask.ethtype); break; case T4_FILTER_MAC_IDX: printf(" %03x/%03x", t->fs.val.macidx, t->fs.mask.macidx); break; case T4_FILTER_MPS_HIT_TYPE: printf(" %1x/%1x", t->fs.val.matchtype, t->fs.mask.matchtype); break; case T4_FILTER_IP_FRAGMENT: printf(" %1d/%1d", t->fs.val.frag, t->fs.mask.frag); break; default: /* compressed filter field not enabled */ break; } } /* * Fixed portion of filter. */ filters_show_ipaddr(t->fs.type, t->fs.val.dip, t->fs.mask.dip); filters_show_ipaddr(t->fs.type, t->fs.val.sip, t->fs.mask.sip); printf(" %04x/%04x %04x/%04x", t->fs.val.dport, t->fs.mask.dport, t->fs.val.sport, t->fs.mask.sport); /* * Variable length filter action. */ if (t->fs.action == FILTER_DROP) printf(" Drop"); else if (t->fs.action == FILTER_SWITCH) { printf(" Switch: port=%d", t->fs.eport); if (t->fs.newdmac) printf( ", dmac=%02x:%02x:%02x:%02x:%02x:%02x " ", l2tidx=%d", t->fs.dmac[0], t->fs.dmac[1], t->fs.dmac[2], t->fs.dmac[3], t->fs.dmac[4], t->fs.dmac[5], t->l2tidx); if (t->fs.newsmac) printf( ", smac=%02x:%02x:%02x:%02x:%02x:%02x " ", smtidx=%d", t->fs.smac[0], t->fs.smac[1], t->fs.smac[2], t->fs.smac[3], t->fs.smac[4], t->fs.smac[5], t->smtidx); if (t->fs.newvlan == VLAN_REMOVE) printf(", vlan=none"); else if (t->fs.newvlan == VLAN_INSERT) printf(", vlan=insert(%x)", t->fs.vlan); else if (t->fs.newvlan == VLAN_REWRITE) printf(", vlan=rewrite(%x)", t->fs.vlan); } else { printf(" Pass: Q="); if (t->fs.dirsteer == 0) { printf("RSS"); if (t->fs.maskhash) printf("(TCB=hash)"); } else { printf("%d", t->fs.iq); if (t->fs.dirsteerhash == 0) printf("(QID)"); else printf("(hash)"); } } if (t->fs.prio) printf(" Prio"); if (t->fs.rpttid) printf(" RptTID"); printf("\n"); } static int show_filters(void) { uint32_t mode = 0, header = 0; struct t4_filter t; int rc; /* Get the global filter mode first */ rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); if (rc != 0) return (rc); t.idx = 0; for (t.idx = 0; ; t.idx++) { rc = doit(CHELSIO_T4_GET_FILTER, &t); if (rc != 0 || t.idx == 0xffffffff) break; if (!header) { do_show_info_header(mode); header = 1; } do_show_one_filter_info(&t, mode); }; return (rc); } static int get_filter_mode(void) { uint32_t mode = 0; int rc; rc = doit(CHELSIO_T4_GET_FILTER_MODE, &mode); if (rc != 0) return (rc); if (mode & T4_FILTER_IPv4) printf("ipv4 "); if (mode & T4_FILTER_IPv6) printf("ipv6 "); if (mode & T4_FILTER_IP_SADDR) printf("sip "); if (mode & T4_FILTER_IP_DADDR) printf("dip "); if (mode & T4_FILTER_IP_SPORT) printf("sport "); if (mode & T4_FILTER_IP_DPORT) printf("dport "); if (mode & T4_FILTER_IP_FRAGMENT) printf("frag "); if (mode & T4_FILTER_MPS_HIT_TYPE) printf("matchtype "); if (mode & T4_FILTER_MAC_IDX) printf("macidx "); if (mode & T4_FILTER_ETH_TYPE) printf("ethtype "); if (mode & T4_FILTER_IP_PROTO) printf("proto "); if (mode & T4_FILTER_IP_TOS) printf("tos "); if (mode & T4_FILTER_VLAN) printf("vlan "); if (mode & T4_FILTER_VNIC) { if (mode & T4_FILTER_IC_VNIC) printf("vnic_id "); else printf("ovlan "); } if (mode & T4_FILTER_PORT) printf("iport "); if (mode & T4_FILTER_FCoE) printf("fcoe "); printf("\n"); return (0); } static int set_filter_mode(int argc, const char *argv[]) { uint32_t mode = 0; int vnic = 0, ovlan = 0; for (; argc; argc--, argv++) { if (!strcmp(argv[0], "frag")) mode |= T4_FILTER_IP_FRAGMENT; if (!strcmp(argv[0], "matchtype")) mode |= T4_FILTER_MPS_HIT_TYPE; if (!strcmp(argv[0], "macidx")) mode |= T4_FILTER_MAC_IDX; if (!strcmp(argv[0], "ethtype")) mode |= T4_FILTER_ETH_TYPE; if (!strcmp(argv[0], "proto")) mode |= T4_FILTER_IP_PROTO; if (!strcmp(argv[0], "tos")) mode |= T4_FILTER_IP_TOS; if (!strcmp(argv[0], "vlan")) mode |= T4_FILTER_VLAN; if (!strcmp(argv[0], "ovlan")) { mode |= T4_FILTER_VNIC; ovlan++; } if (!strcmp(argv[0], "vnic_id")) { mode |= T4_FILTER_VNIC; mode |= T4_FILTER_IC_VNIC; vnic++; } if (!strcmp(argv[0], "iport")) mode |= T4_FILTER_PORT; if (!strcmp(argv[0], "fcoe")) mode |= T4_FILTER_FCoE; } if (vnic > 0 && ovlan > 0) { warnx("\"vnic_id\" and \"ovlan\" are mutually exclusive."); return (EINVAL); } return doit(CHELSIO_T4_SET_FILTER_MODE, &mode); } static int del_filter(uint32_t idx) { struct t4_filter t; t.idx = idx; return doit(CHELSIO_T4_DEL_FILTER, &t); } static int set_filter(uint32_t idx, int argc, const char *argv[]) { int af = AF_UNSPEC, start_arg = 0; struct t4_filter t; if (argc < 2) { warnc(EINVAL, "%s", __func__); return (EINVAL); }; bzero(&t, sizeof (t)); t.idx = idx; t.fs.hitcnts = 1; for (start_arg = 0; start_arg + 2 <= argc; start_arg += 2) { const char **args = &argv[start_arg]; uint32_t val, mask; if (!strcmp(argv[start_arg], "type")) { int newaf; if (!strcasecmp(argv[start_arg + 1], "ipv4")) newaf = AF_INET; else if (!strcasecmp(argv[start_arg + 1], "ipv6")) newaf = AF_INET6; else { warnx("invalid type \"%s\"; " "must be one of \"ipv4\" or \"ipv6\"", argv[start_arg + 1]); return (EINVAL); } if (af != AF_UNSPEC && af != newaf) { warnx("conflicting IPv4/IPv6 specifications."); return (EINVAL); } af = newaf; } else if (!parse_val_mask("fcoe", args, &val, &mask)) { t.fs.val.fcoe = val; t.fs.mask.fcoe = mask; } else if (!parse_val_mask("iport", args, &val, &mask)) { t.fs.val.iport = val; t.fs.mask.iport = mask; } else if (!parse_val_mask("ovlan", args, &val, &mask)) { t.fs.val.vnic = val; t.fs.mask.vnic = mask; t.fs.val.ovlan_vld = 1; t.fs.mask.ovlan_vld = 1; } else if (!parse_val_mask("ivlan", args, &val, &mask)) { t.fs.val.vlan = val; t.fs.mask.vlan = mask; t.fs.val.vlan_vld = 1; t.fs.mask.vlan_vld = 1; } else if (!parse_val_mask("pf", args, &val, &mask)) { t.fs.val.vnic &= 0x1fff; t.fs.val.vnic |= (val & 0x7) << 13; t.fs.mask.vnic &= 0x1fff; t.fs.mask.vnic |= (mask & 0x7) << 13; t.fs.val.pfvf_vld = 1; t.fs.mask.pfvf_vld = 1; } else if (!parse_val_mask("vf", args, &val, &mask)) { t.fs.val.vnic &= 0xe000; t.fs.val.vnic |= val & 0x1fff; t.fs.mask.vnic &= 0xe000; t.fs.mask.vnic |= mask & 0x1fff; t.fs.val.pfvf_vld = 1; t.fs.mask.pfvf_vld = 1; } else if (!parse_val_mask("tos", args, &val, &mask)) { t.fs.val.tos = val; t.fs.mask.tos = mask; } else if (!parse_val_mask("proto", args, &val, &mask)) { t.fs.val.proto = val; t.fs.mask.proto = mask; } else if (!parse_val_mask("ethtype", args, &val, &mask)) { t.fs.val.ethtype = val; t.fs.mask.ethtype = mask; } else if (!parse_val_mask("macidx", args, &val, &mask)) { t.fs.val.macidx = val; t.fs.mask.macidx = mask; } else if (!parse_val_mask("matchtype", args, &val, &mask)) { t.fs.val.matchtype = val; t.fs.mask.matchtype = mask; } else if (!parse_val_mask("frag", args, &val, &mask)) { t.fs.val.frag = val; t.fs.mask.frag = mask; } else if (!parse_val_mask("dport", args, &val, &mask)) { t.fs.val.dport = val; t.fs.mask.dport = mask; } else if (!parse_val_mask("sport", args, &val, &mask)) { t.fs.val.sport = val; t.fs.mask.sport = mask; } else if (!parse_ipaddr("dip", args, &af, t.fs.val.dip, t.fs.mask.dip)) { /* nada */; } else if (!parse_ipaddr("sip", args, &af, t.fs.val.sip, t.fs.mask.sip)) { /* nada */; } else if (!strcmp(argv[start_arg], "action")) { if (!strcmp(argv[start_arg + 1], "pass")) t.fs.action = FILTER_PASS; else if (!strcmp(argv[start_arg + 1], "drop")) t.fs.action = FILTER_DROP; else if (!strcmp(argv[start_arg + 1], "switch")) t.fs.action = FILTER_SWITCH; else { warnx("invalid action \"%s\"; must be one of" " \"pass\", \"drop\" or \"switch\"", argv[start_arg + 1]); return (EINVAL); } } else if (!parse_val("hitcnts", args, &val)) { t.fs.hitcnts = val; } else if (!parse_val("prio", args, &val)) { t.fs.prio = val; } else if (!parse_val("rpttid", args, &val)) { t.fs.rpttid = 1; } else if (!parse_val("queue", args, &val)) { t.fs.dirsteer = 1; t.fs.iq = val; } else if (!parse_val("tcbhash", args, &val)) { t.fs.maskhash = 1; t.fs.dirsteerhash = 1; } else if (!parse_val("eport", args, &val)) { t.fs.eport = val; } else if (!strcmp(argv[start_arg], "dmac")) { struct ether_addr *daddr; daddr = ether_aton(argv[start_arg + 1]); if (daddr == NULL) { warnx("invalid dmac address \"%s\"", argv[start_arg + 1]); return (EINVAL); } memcpy(t.fs.dmac, daddr, ETHER_ADDR_LEN); t.fs.newdmac = 1; } else if (!strcmp(argv[start_arg], "smac")) { struct ether_addr *saddr; saddr = ether_aton(argv[start_arg + 1]); if (saddr == NULL) { warnx("invalid smac address \"%s\"", argv[start_arg + 1]); return (EINVAL); } memcpy(t.fs.smac, saddr, ETHER_ADDR_LEN); t.fs.newsmac = 1; } else if (!strcmp(argv[start_arg], "vlan")) { char *p; if (!strcmp(argv[start_arg + 1], "none")) { t.fs.newvlan = VLAN_REMOVE; } else if (argv[start_arg + 1][0] == '=') { t.fs.newvlan = VLAN_REWRITE; } else if (argv[start_arg + 1][0] == '+') { t.fs.newvlan = VLAN_INSERT; } else if (isdigit(argv[start_arg + 1][0]) && !parse_val_mask("vlan", args, &val, &mask)) { t.fs.val.vlan = val; t.fs.mask.vlan = mask; t.fs.val.vlan_vld = 1; t.fs.mask.vlan_vld = 1; } else { warnx("unknown vlan parameter \"%s\"; must" " be one of \"none\", \"=\", " " \"+\", or \"\"", argv[start_arg + 1]); return (EINVAL); } if (t.fs.newvlan == VLAN_REWRITE || t.fs.newvlan == VLAN_INSERT) { t.fs.vlan = strtoul(argv[start_arg + 1] + 1, &p, 0); if (p == argv[start_arg + 1] + 1 || p[0] != 0) { warnx("invalid vlan \"%s\"", argv[start_arg + 1]); return (EINVAL); } } } else { warnx("invalid parameter \"%s\"", argv[start_arg]); return (EINVAL); } } if (start_arg != argc) { warnx("no value for \"%s\"", argv[start_arg]); return (EINVAL); } /* * Check basic sanity of option combinations. */ if (t.fs.action != FILTER_SWITCH && (t.fs.eport || t.fs.newdmac || t.fs.newsmac || t.fs.newvlan)) { warnx("prio, port dmac, smac and vlan only make sense with" " \"action switch\""); return (EINVAL); } if (t.fs.action != FILTER_PASS && (t.fs.rpttid || t.fs.dirsteer || t.fs.maskhash)) { warnx("rpttid, queue and tcbhash don't make sense with" " action \"drop\" or \"switch\""); return (EINVAL); } if (t.fs.val.ovlan_vld && t.fs.val.pfvf_vld) { warnx("ovlan and vnic_id (pf/vf) are mutually exclusive"); return (EINVAL); } t.fs.type = (af == AF_INET6 ? 1 : 0); /* default IPv4 */ return doit(CHELSIO_T4_SET_FILTER, &t); } static int filter_cmd(int argc, const char *argv[]) { long long val; uint32_t idx; char *s; if (argc == 0) { warnx("filter: no arguments."); return (EINVAL); }; /* list */ if (strcmp(argv[0], "list") == 0) { if (argc != 1) warnx("trailing arguments after \"list\" ignored."); return show_filters(); } /* mode */ if (argc == 1 && strcmp(argv[0], "mode") == 0) return get_filter_mode(); /* mode */ if (strcmp(argv[0], "mode") == 0) return set_filter_mode(argc - 1, argv + 1); /* ... */ s = str_to_number(argv[0], NULL, &val); if (*s || val > 0xffffffffU) { warnx("\"%s\" is neither an index nor a filter subcommand.", argv[0]); return (EINVAL); } idx = (uint32_t) val; /* delete|clear */ if (argc == 2 && (strcmp(argv[1], "delete") == 0 || strcmp(argv[1], "clear") == 0)) { return del_filter(idx); } /* [ ] ... */ return set_filter(idx, argc - 1, argv + 1); } /* * Shows the fields of a multi-word structure. The structure is considered to * consist of @nwords 32-bit words (i.e, it's an (@nwords * 32)-bit structure) * whose fields are described by @fd. The 32-bit words are given in @words * starting with the least significant 32-bit word. */ static void show_struct(const uint32_t *words, int nwords, const struct field_desc *fd) { unsigned int w = 0; const struct field_desc *p; for (p = fd; p->name; p++) w = max(w, strlen(p->name)); while (fd->name) { unsigned long long data; int first_word = fd->start / 32; int shift = fd->start % 32; int width = fd->end - fd->start + 1; unsigned long long mask = (1ULL << width) - 1; data = (words[first_word] >> shift) | ((uint64_t)words[first_word + 1] << (32 - shift)); if (shift) data |= ((uint64_t)words[first_word + 2] << (64 - shift)); data &= mask; if (fd->islog2) data = 1 << data; printf("%-*s ", w, fd->name); printf(fd->hex ? "%#llx\n" : "%llu\n", data << fd->shift); fd++; } } #define FIELD(name, start, end) { name, start, end, 0, 0, 0 } #define FIELD1(name, start) FIELD(name, start, start) static void show_t5t6_ctxt(const struct t4_sge_context *p, int vers) { static struct field_desc egress_t5[] = { FIELD("DCA_ST:", 181, 191), FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("StatusPgTPHintEn:", 173), FIELD("StatusPgTPHint:", 171, 172), FIELD1("FetchTPHintEn:", 170), FIELD("FetchTPHint:", 168, 169), FIELD1("FCThreshOverride:", 167), { "WRLength:", 162, 166, 9, 0, 1 }, FIELD1("WRLengthKnown:", 161), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode:", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, FIELD1("FLMPacking:", 155), FIELD("FetchBurstMax:", 153, 154), FIELD("uPToken:", 133, 152), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc egress_t6[] = { FIELD("DCA_ST:", 181, 191), FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD1("ReschedulePending_1:", 175), FIELD1("PCIeDataChannel:", 174), FIELD1("StatusPgTPHintEn:", 173), FIELD("StatusPgTPHint:", 171, 172), FIELD1("FetchTPHintEn:", 170), FIELD("FetchTPHint:", 168, 169), FIELD1("FCThreshOverride:", 167), { "WRLength:", 162, 166, 9, 0, 1 }, FIELD1("WRLengthKnown:", 161), FIELD1("ReschedulePending:", 160), FIELD("TimerIx:", 157, 159), FIELD1("FetchBurstMin:", 156), FIELD1("FLMPacking:", 155), FIELD("FetchBurstMax:", 153, 154), FIELD("uPToken:", 133, 152), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("FetchSizeMode:", 0), { NULL } }; static struct field_desc fl_t5[] = { FIELD("DCA_ST:", 181, 191), FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("StatusPgTPHintEn:", 173), FIELD("StatusPgTPHint:", 171, 172), FIELD1("FetchTPHintEn:", 170), FIELD("FetchTPHint:", 168, 169), FIELD1("FCThreshOverride:", 167), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode:", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, FIELD1("FLMPacking:", 155), FIELD("FetchBurstMax:", 153, 154), FIELD1("FLMcongMode:", 152), FIELD("MaxuPFLCredits:", 144, 151), FIELD("FLMcontextID:", 133, 143), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc ingress_t5[] = { FIELD("DCA_ST:", 143, 153), FIELD1("ISCSICoalescing:", 142), FIELD1("Queue_Valid:", 141), FIELD1("TimerPending:", 140), FIELD1("DropRSS:", 139), FIELD("PCIeChannel:", 137, 138), FIELD1("SEInterruptArmed:", 136), FIELD1("CongestionMgtEnable:", 135), FIELD1("NoSnoop:", 134), FIELD1("RelaxedOrdering:", 133), FIELD1("GTSmode:", 132), FIELD1("TPHintEn:", 131), FIELD("TPHint:", 129, 130), FIELD1("UpdateScheduling:", 128), FIELD("UpdateDelivery:", 126, 127), FIELD1("InterruptSent:", 125), FIELD("InterruptIDX:", 114, 124), FIELD1("InterruptDestination:", 113), FIELD1("InterruptArmed:", 112), FIELD("RxIntCounter:", 106, 111), FIELD("RxIntCounterThreshold:", 104, 105), FIELD1("Generation:", 103), { "BaseAddress:", 48, 102, 9, 1 }, FIELD("PIDX:", 32, 47), FIELD("CIDX:", 16, 31), { "QueueSize:", 4, 15, 4, 0 }, { "QueueEntrySize:", 2, 3, 4, 0, 1 }, FIELD1("QueueEntryOverride:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc ingress_t6[] = { FIELD1("SP_NS:", 158), FIELD1("SP_RO:", 157), FIELD1("SP_TPHintEn:", 156), FIELD("SP_TPHint:", 154, 155), FIELD("DCA_ST:", 143, 153), FIELD1("ISCSICoalescing:", 142), FIELD1("Queue_Valid:", 141), FIELD1("TimerPending:", 140), FIELD1("DropRSS:", 139), FIELD("PCIeChannel:", 137, 138), FIELD1("SEInterruptArmed:", 136), FIELD1("CongestionMgtEnable:", 135), FIELD1("NoSnoop:", 134), FIELD1("RelaxedOrdering:", 133), FIELD1("GTSmode:", 132), FIELD1("TPHintEn:", 131), FIELD("TPHint:", 129, 130), FIELD1("UpdateScheduling:", 128), FIELD("UpdateDelivery:", 126, 127), FIELD1("InterruptSent:", 125), FIELD("InterruptIDX:", 114, 124), FIELD1("InterruptDestination:", 113), FIELD1("InterruptArmed:", 112), FIELD("RxIntCounter:", 106, 111), FIELD("RxIntCounterThreshold:", 104, 105), FIELD1("Generation:", 103), { "BaseAddress:", 48, 102, 9, 1 }, FIELD("PIDX:", 32, 47), FIELD("CIDX:", 16, 31), { "QueueSize:", 4, 15, 4, 0 }, { "QueueEntrySize:", 2, 3, 4, 0, 1 }, FIELD1("QueueEntryOverride:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc flm_t5[] = { FIELD1("Valid:", 89), FIELD("SplitLenMode:", 87, 88), FIELD1("TPHintEn:", 86), FIELD("TPHint:", 84, 85), FIELD1("NoSnoop:", 83), FIELD1("RelaxedOrdering:", 82), FIELD("DCA_ST:", 71, 81), FIELD("EQid:", 54, 70), FIELD("SplitEn:", 52, 53), FIELD1("PadEn:", 51), FIELD1("PackEn:", 50), FIELD1("Cache_Lock :", 49), FIELD1("CongDrop:", 48), FIELD("PackOffset:", 16, 47), FIELD("CIDX:", 8, 15), FIELD("PIDX:", 0, 7), { NULL } }; static struct field_desc flm_t6[] = { FIELD1("Valid:", 89), FIELD("SplitLenMode:", 87, 88), FIELD1("TPHintEn:", 86), FIELD("TPHint:", 84, 85), FIELD1("NoSnoop:", 83), FIELD1("RelaxedOrdering:", 82), FIELD("DCA_ST:", 71, 81), FIELD("EQid:", 54, 70), FIELD("SplitEn:", 52, 53), FIELD1("PadEn:", 51), FIELD1("PackEn:", 50), FIELD1("Cache_Lock :", 49), FIELD1("CongDrop:", 48), FIELD1("Inflight:", 47), FIELD1("CongEn:", 46), FIELD1("CongMode:", 45), FIELD("PackOffset:", 20, 39), FIELD("CIDX:", 8, 15), FIELD("PIDX:", 0, 7), { NULL } }; static struct field_desc conm_t5[] = { FIELD1("CngMPSEnable:", 21), FIELD("CngTPMode:", 19, 20), FIELD1("CngDBPHdr:", 18), FIELD1("CngDBPData:", 17), FIELD1("CngIMSG:", 16), { "CngChMap:", 0, 15, 0, 1, 0 }, { NULL } }; if (p->mem_id == SGE_CONTEXT_EGRESS) { if (p->data[0] & 2) show_struct(p->data, 6, fl_t5); else if (vers == 5) show_struct(p->data, 6, egress_t5); else show_struct(p->data, 6, egress_t6); } else if (p->mem_id == SGE_CONTEXT_FLM) show_struct(p->data, 3, vers == 5 ? flm_t5 : flm_t6); else if (p->mem_id == SGE_CONTEXT_INGRESS) show_struct(p->data, 5, vers == 5 ? ingress_t5 : ingress_t6); else if (p->mem_id == SGE_CONTEXT_CNM) show_struct(p->data, 1, conm_t5); } static void show_t4_ctxt(const struct t4_sge_context *p) { static struct field_desc egress_t4[] = { FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("DCAEgrQEn:", 173), FIELD("DCACPUID:", 168, 172), FIELD1("FCThreshOverride:", 167), FIELD("WRLength:", 162, 166), FIELD1("WRLengthKnown:", 161), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, { "FetchBurstMax:", 153, 154, 6, 0, 1 }, FIELD("uPToken:", 133, 152), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc fl_t4[] = { FIELD1("StatusPgNS:", 180), FIELD1("StatusPgRO:", 179), FIELD1("FetchNS:", 178), FIELD1("FetchRO:", 177), FIELD1("Valid:", 176), FIELD("PCIeDataChannel:", 174, 175), FIELD1("DCAEgrQEn:", 173), FIELD("DCACPUID:", 168, 172), FIELD1("FCThreshOverride:", 167), FIELD1("ReschedulePending:", 160), FIELD1("OnChipQueue:", 159), FIELD1("FetchSizeMode", 158), { "FetchBurstMin:", 156, 157, 4, 0, 1 }, { "FetchBurstMax:", 153, 154, 6, 0, 1 }, FIELD1("FLMcongMode:", 152), FIELD("MaxuPFLCredits:", 144, 151), FIELD("FLMcontextID:", 133, 143), FIELD1("uPTokenEn:", 132), FIELD1("UserModeIO:", 131), FIELD("uPFLCredits:", 123, 130), FIELD1("uPFLCreditEn:", 122), FIELD("FID:", 111, 121), FIELD("HostFCMode:", 109, 110), FIELD1("HostFCOwner:", 108), { "CIDXFlushThresh:", 105, 107, 0, 0, 1 }, FIELD("CIDX:", 89, 104), FIELD("PIDX:", 73, 88), { "BaseAddress:", 18, 72, 9, 1 }, FIELD("QueueSize:", 2, 17), FIELD1("QueueType:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc ingress_t4[] = { FIELD1("NoSnoop:", 145), FIELD1("RelaxedOrdering:", 144), FIELD1("GTSmode:", 143), FIELD1("ISCSICoalescing:", 142), FIELD1("Valid:", 141), FIELD1("TimerPending:", 140), FIELD1("DropRSS:", 139), FIELD("PCIeChannel:", 137, 138), FIELD1("SEInterruptArmed:", 136), FIELD1("CongestionMgtEnable:", 135), FIELD1("DCAIngQEnable:", 134), FIELD("DCACPUID:", 129, 133), FIELD1("UpdateScheduling:", 128), FIELD("UpdateDelivery:", 126, 127), FIELD1("InterruptSent:", 125), FIELD("InterruptIDX:", 114, 124), FIELD1("InterruptDestination:", 113), FIELD1("InterruptArmed:", 112), FIELD("RxIntCounter:", 106, 111), FIELD("RxIntCounterThreshold:", 104, 105), FIELD1("Generation:", 103), { "BaseAddress:", 48, 102, 9, 1 }, FIELD("PIDX:", 32, 47), FIELD("CIDX:", 16, 31), { "QueueSize:", 4, 15, 4, 0 }, { "QueueEntrySize:", 2, 3, 4, 0, 1 }, FIELD1("QueueEntryOverride:", 1), FIELD1("CachePriority:", 0), { NULL } }; static struct field_desc flm_t4[] = { FIELD1("NoSnoop:", 79), FIELD1("RelaxedOrdering:", 78), FIELD1("Valid:", 77), FIELD("DCACPUID:", 72, 76), FIELD1("DCAFLEn:", 71), FIELD("EQid:", 54, 70), FIELD("SplitEn:", 52, 53), FIELD1("PadEn:", 51), FIELD1("PackEn:", 50), FIELD1("DBpriority:", 48), FIELD("PackOffset:", 16, 47), FIELD("CIDX:", 8, 15), FIELD("PIDX:", 0, 7), { NULL } }; static struct field_desc conm_t4[] = { FIELD1("CngDBPHdr:", 6), FIELD1("CngDBPData:", 5), FIELD1("CngIMSG:", 4), { "CngChMap:", 0, 3, 0, 1, 0}, { NULL } }; if (p->mem_id == SGE_CONTEXT_EGRESS) show_struct(p->data, 6, (p->data[0] & 2) ? fl_t4 : egress_t4); else if (p->mem_id == SGE_CONTEXT_FLM) show_struct(p->data, 3, flm_t4); else if (p->mem_id == SGE_CONTEXT_INGRESS) show_struct(p->data, 5, ingress_t4); else if (p->mem_id == SGE_CONTEXT_CNM) show_struct(p->data, 1, conm_t4); } #undef FIELD #undef FIELD1 static int get_sge_context(int argc, const char *argv[]) { int rc; char *p; long cid; struct t4_sge_context cntxt = {0}; if (argc != 2) { warnx("sge_context: incorrect number of arguments."); return (EINVAL); } if (!strcmp(argv[0], "egress")) cntxt.mem_id = SGE_CONTEXT_EGRESS; else if (!strcmp(argv[0], "ingress")) cntxt.mem_id = SGE_CONTEXT_INGRESS; else if (!strcmp(argv[0], "fl")) cntxt.mem_id = SGE_CONTEXT_FLM; else if (!strcmp(argv[0], "cong")) cntxt.mem_id = SGE_CONTEXT_CNM; else { warnx("unknown context type \"%s\"; known types are egress, " "ingress, fl, and cong.", argv[0]); return (EINVAL); } p = str_to_number(argv[1], &cid, NULL); if (*p) { warnx("invalid context id \"%s\"", argv[1]); return (EINVAL); } cntxt.cid = cid; rc = doit(CHELSIO_T4_GET_SGE_CONTEXT, &cntxt); if (rc != 0) return (rc); if (chip_id == 4) show_t4_ctxt(&cntxt); else show_t5t6_ctxt(&cntxt, chip_id); return (0); } static int loadfw(int argc, const char *argv[]) { int rc, fd; struct t4_data data = {0}; const char *fname = argv[0]; struct stat st = {0}; if (argc != 1) { warnx("loadfw: incorrect number of arguments."); return (EINVAL); } fd = open(fname, O_RDONLY); if (fd < 0) { warn("open(%s)", fname); return (errno); } if (fstat(fd, &st) < 0) { warn("fstat"); close(fd); return (errno); } data.len = st.st_size; data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); if (data.data == MAP_FAILED) { warn("mmap"); close(fd); return (errno); } rc = doit(CHELSIO_T4_LOAD_FW, &data); munmap(data.data, data.len); close(fd); return (rc); } static int loadcfg(int argc, const char *argv[]) { int rc, fd; struct t4_data data = {0}; const char *fname = argv[0]; struct stat st = {0}; if (argc != 1) { warnx("loadcfg: incorrect number of arguments."); return (EINVAL); } if (strcmp(fname, "clear") == 0) return (doit(CHELSIO_T4_LOAD_CFG, &data)); fd = open(fname, O_RDONLY); if (fd < 0) { warn("open(%s)", fname); return (errno); } if (fstat(fd, &st) < 0) { warn("fstat"); close(fd); return (errno); } data.len = st.st_size; data.len &= ~3; /* Clip off to make it a multiple of 4 */ data.data = mmap(0, data.len, PROT_READ, MAP_PRIVATE, fd, 0); if (data.data == MAP_FAILED) { warn("mmap"); close(fd); return (errno); } rc = doit(CHELSIO_T4_LOAD_CFG, &data); munmap(data.data, data.len); close(fd); return (rc); } static int +dumpstate(int argc, const char *argv[]) +{ + int rc, fd; + struct t4_cudbg_dump dump = {0}; + const char *fname = argv[0]; + + if (argc != 1) { + warnx("dumpstate: incorrect number of arguments."); + return (EINVAL); + } + + fd = open(fname, O_CREAT | O_TRUNC | O_EXCL | O_WRONLY); + if (fd < 0) { + warn("open(%s)", fname); + return (errno); + } + + dump.wr_flash = 0; + memset(&dump.bitmap, 0xff, sizeof(dump.bitmap)); + dump.len = 8 * 1024 * 1024; + dump.data = malloc(dump.len); + if (dump.data == NULL) { + close(fd); + return (ENOMEM); + } + + rc = doit(CHELSIO_T4_CUDBG_DUMP, &dump); + write(fd, dump.data, dump.len); + free(dump.data); + close(fd); + return (rc); +} + +static int read_mem(uint32_t addr, uint32_t len, void (*output)(uint32_t *, uint32_t)) { int rc; struct t4_mem_range mr; mr.addr = addr; mr.len = len; mr.data = malloc(mr.len); if (mr.data == 0) { warn("read_mem: malloc"); return (errno); } rc = doit(CHELSIO_T4_GET_MEM, &mr); if (rc != 0) goto done; if (output) (*output)(mr.data, mr.len); done: free(mr.data); return (rc); } static int loadboot(int argc, const char *argv[]) { int rc, fd; long l; char *p; struct t4_bootrom br = {0}; const char *fname = argv[0]; struct stat st = {0}; if (argc == 1) { br.pf_offset = 0; br.pfidx_addr = 0; } else if (argc == 3) { if (!strcmp(argv[1], "pf")) br.pf_offset = 0; else if (!strcmp(argv[1], "offset")) br.pf_offset = 1; else return (EINVAL); p = str_to_number(argv[2], &l, NULL); if (*p) return (EINVAL); br.pfidx_addr = l; } else { warnx("loadboot: incorrect number of arguments."); return (EINVAL); } if (strcmp(fname, "clear") == 0) return (doit(CHELSIO_T4_LOAD_BOOT, &br)); fd = open(fname, O_RDONLY); if (fd < 0) { warn("open(%s)", fname); return (errno); } if (fstat(fd, &st) < 0) { warn("fstat"); close(fd); return (errno); } br.len = st.st_size; br.data = mmap(0, br.len, PROT_READ, MAP_PRIVATE, fd, 0); if (br.data == MAP_FAILED) { warn("mmap"); close(fd); return (errno); } rc = doit(CHELSIO_T4_LOAD_BOOT, &br); munmap(br.data, br.len); close(fd); return (rc); } static int loadbootcfg(int argc, const char *argv[]) { int rc, fd; struct t4_data bc = {0}; const char *fname = argv[0]; struct stat st = {0}; if (argc != 1) { warnx("loadbootcfg: incorrect number of arguments."); return (EINVAL); } if (strcmp(fname, "clear") == 0) return (doit(CHELSIO_T4_LOAD_BOOTCFG, &bc)); fd = open(fname, O_RDONLY); if (fd < 0) { warn("open(%s)", fname); return (errno); } if (fstat(fd, &st) < 0) { warn("fstat"); close(fd); return (errno); } bc.len = st.st_size; bc.data = mmap(0, bc.len, PROT_READ, MAP_PRIVATE, fd, 0); if (bc.data == MAP_FAILED) { warn("mmap"); close(fd); return (errno); } rc = doit(CHELSIO_T4_LOAD_BOOTCFG, &bc); munmap(bc.data, bc.len); close(fd); return (rc); } /* * Display memory as list of 'n' 4-byte values per line. */ static void show_mem(uint32_t *buf, uint32_t len) { const char *s; int i, n = 8; while (len) { for (i = 0; len && i < n; i++, buf++, len -= 4) { s = i ? " " : ""; printf("%s%08x", s, htonl(*buf)); } printf("\n"); } } static int memdump(int argc, const char *argv[]) { char *p; long l; uint32_t addr, len; if (argc != 2) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid address \"%s\"", argv[0]); return (EINVAL); } addr = l; p = str_to_number(argv[1], &l, NULL); if (*p) { warnx("memdump: invalid length \"%s\"", argv[1]); return (EINVAL); } len = l; return (read_mem(addr, len, show_mem)); } /* * Display TCB as list of 'n' 4-byte values per line. */ static void show_tcb(uint32_t *buf, uint32_t len) { const char *s; int i, n = 8; while (len) { for (i = 0; len && i < n; i++, buf++, len -= 4) { s = i ? " " : ""; printf("%s%08x", s, htonl(*buf)); } printf("\n"); } } #define A_TP_CMM_TCB_BASE 0x7d10 #define TCB_SIZE 128 static int read_tcb(int argc, const char *argv[]) { char *p; long l; long long val; unsigned int tid; uint32_t addr; int rc; if (argc != 1) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid tid \"%s\"", argv[0]); return (EINVAL); } tid = l; rc = read_reg(A_TP_CMM_TCB_BASE, 4, &val); if (rc != 0) return (rc); addr = val + tid * TCB_SIZE; return (read_mem(addr, TCB_SIZE, show_tcb)); } static int read_i2c(int argc, const char *argv[]) { char *p; long l; struct t4_i2c_data i2cd; int rc, i; if (argc < 3 || argc > 4) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } i2cd.port_id = l; p = str_to_number(argv[1], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid i2c device address \"%s\"", argv[1]); return (EINVAL); } i2cd.dev_addr = l; p = str_to_number(argv[2], &l, NULL); if (*p || l > UCHAR_MAX) { warnx("invalid byte offset \"%s\"", argv[2]); return (EINVAL); } i2cd.offset = l; if (argc == 4) { p = str_to_number(argv[3], &l, NULL); if (*p || l > sizeof(i2cd.data)) { warnx("invalid number of bytes \"%s\"", argv[3]); return (EINVAL); } i2cd.len = l; } else i2cd.len = 1; rc = doit(CHELSIO_T4_GET_I2C, &i2cd); if (rc != 0) return (rc); for (i = 0; i < i2cd.len; i++) printf("0x%x [%u]\n", i2cd.data[i], i2cd.data[i]); return (0); } static int clearstats(int argc, const char *argv[]) { char *p; long l; uint32_t port; if (argc != 1) { warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &l, NULL); if (*p) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } port = l; return doit(CHELSIO_T4_CLEAR_STATS, &port); } static int show_tracers(void) { struct t4_tracer t; char *s; int rc, port_idx, i; long long val; /* Magic values: MPS_TRC_CFG = 0x9800. MPS_TRC_CFG[1:1] = TrcEn */ rc = read_reg(0x9800, 4, &val); if (rc != 0) return (rc); printf("tracing is %s\n", val & 2 ? "ENABLED" : "DISABLED"); t.idx = 0; for (t.idx = 0; ; t.idx++) { rc = doit(CHELSIO_T4_GET_TRACER, &t); if (rc != 0 || t.idx == 0xff) break; if (t.tp.port < 4) { s = "Rx"; port_idx = t.tp.port; } else if (t.tp.port < 8) { s = "Tx"; port_idx = t.tp.port - 4; } else if (t.tp.port < 12) { s = "loopback"; port_idx = t.tp.port - 8; } else if (t.tp.port < 16) { s = "MPS Rx"; port_idx = t.tp.port - 12; } else if (t.tp.port < 20) { s = "MPS Tx"; port_idx = t.tp.port - 16; } else { s = "unknown"; port_idx = t.tp.port; } printf("\ntracer %u (currently %s) captures ", t.idx, t.enabled ? "ENABLED" : "DISABLED"); if (t.tp.port < 8) printf("port %u %s, ", port_idx, s); else printf("%s %u, ", s, port_idx); printf("snap length: %u, min length: %u\n", t.tp.snap_len, t.tp.min_len); printf("packets captured %smatch filter\n", t.tp.invert ? "do not " : ""); if (t.tp.skip_ofst) { printf("filter pattern: "); for (i = 0; i < t.tp.skip_ofst * 2; i += 2) printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); printf("/"); for (i = 0; i < t.tp.skip_ofst * 2; i += 2) printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); printf("@0\n"); } printf("filter pattern: "); for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) printf("%08x%08x", t.tp.data[i], t.tp.data[i + 1]); printf("/"); for (i = t.tp.skip_ofst * 2; i < T4_TRACE_LEN / 4; i += 2) printf("%08x%08x", t.tp.mask[i], t.tp.mask[i + 1]); printf("@%u\n", (t.tp.skip_ofst + t.tp.skip_len) * 8); } return (rc); } static int tracer_onoff(uint8_t idx, int enabled) { struct t4_tracer t; t.idx = idx; t.enabled = enabled; t.valid = 0; return doit(CHELSIO_T4_SET_TRACER, &t); } static void create_tracing_ifnet() { char *cmd[] = { "/sbin/ifconfig", __DECONST(char *, nexus), "create", NULL }; char *env[] = {NULL}; if (vfork() == 0) { close(STDERR_FILENO); execve(cmd[0], cmd, env); _exit(0); } } /* * XXX: Allow user to specify snaplen, minlen, and pattern (including inverted * matching). Right now this is a quick-n-dirty implementation that traces the * first 128B of all tx or rx on a port */ static int set_tracer(uint8_t idx, int argc, const char *argv[]) { struct t4_tracer t; int len, port; bzero(&t, sizeof (t)); t.idx = idx; t.enabled = 1; t.valid = 1; if (argc != 1) { warnx("must specify tx or rx."); return (EINVAL); } len = strlen(argv[0]); if (len != 3) { warnx("argument must be 3 characters (tx or rx)"); return (EINVAL); } if (strncmp(argv[0], "tx", 2) == 0) { port = argv[0][2] - '0'; if (port < 0 || port > 3) { warnx("'%c' in %s is invalid", argv[0][2], argv[0]); return (EINVAL); } port += 4; } else if (strncmp(argv[0], "rx", 2) == 0) { port = argv[0][2] - '0'; if (port < 0 || port > 3) { warnx("'%c' in %s is invalid", argv[0][2], argv[0]); return (EINVAL); } } else { warnx("argument '%s' isn't tx or rx", argv[0]); return (EINVAL); } t.tp.snap_len = 128; t.tp.min_len = 0; t.tp.skip_ofst = 0; t.tp.skip_len = 0; t.tp.invert = 0; t.tp.port = port; create_tracing_ifnet(); return doit(CHELSIO_T4_SET_TRACER, &t); } static int tracer_cmd(int argc, const char *argv[]) { long long val; uint8_t idx; char *s; if (argc == 0) { warnx("tracer: no arguments."); return (EINVAL); }; /* list */ if (strcmp(argv[0], "list") == 0) { if (argc != 1) warnx("trailing arguments after \"list\" ignored."); return show_tracers(); } /* ... */ s = str_to_number(argv[0], NULL, &val); if (*s || val > 0xff) { warnx("\"%s\" is neither an index nor a tracer subcommand.", argv[0]); return (EINVAL); } idx = (int8_t)val; /* disable */ if (argc == 2 && strcmp(argv[1], "disable") == 0) return tracer_onoff(idx, 0); /* enable */ if (argc == 2 && strcmp(argv[1], "enable") == 0) return tracer_onoff(idx, 1); /* ... */ return set_tracer(idx, argc - 1, argv + 1); } static int modinfo_raw(int port_id) { uint8_t offset; struct t4_i2c_data i2cd; int rc; for (offset = 0; offset < 96; offset += sizeof(i2cd.data)) { bzero(&i2cd, sizeof(i2cd)); i2cd.port_id = port_id; i2cd.dev_addr = 0xa0; i2cd.offset = offset; i2cd.len = sizeof(i2cd.data); rc = doit(CHELSIO_T4_GET_I2C, &i2cd); if (rc != 0) return (rc); printf("%02x: %02x %02x %02x %02x %02x %02x %02x %02x", offset, i2cd.data[0], i2cd.data[1], i2cd.data[2], i2cd.data[3], i2cd.data[4], i2cd.data[5], i2cd.data[6], i2cd.data[7]); printf(" %c%c%c%c %c%c%c%c\n", isprint(i2cd.data[0]) ? i2cd.data[0] : '.', isprint(i2cd.data[1]) ? i2cd.data[1] : '.', isprint(i2cd.data[2]) ? i2cd.data[2] : '.', isprint(i2cd.data[3]) ? i2cd.data[3] : '.', isprint(i2cd.data[4]) ? i2cd.data[4] : '.', isprint(i2cd.data[5]) ? i2cd.data[5] : '.', isprint(i2cd.data[6]) ? i2cd.data[6] : '.', isprint(i2cd.data[7]) ? i2cd.data[7] : '.'); } return (0); } static int modinfo(int argc, const char *argv[]) { long port; char string[16], *p; struct t4_i2c_data i2cd; int rc, i; uint16_t temp, vcc, tx_bias, tx_power, rx_power; if (argc < 1) { warnx("must supply a port"); return (EINVAL); } if (argc > 2) { warnx("too many arguments"); return (EINVAL); } p = str_to_number(argv[0], &port, NULL); if (*p || port > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } if (argc == 2) { if (!strcmp(argv[1], "raw")) return (modinfo_raw(port)); else { warnx("second argument can only be \"raw\""); return (EINVAL); } } bzero(&i2cd, sizeof(i2cd)); i2cd.len = 1; i2cd.port_id = port; i2cd.dev_addr = SFF_8472_BASE; i2cd.offset = SFF_8472_ID; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; if (i2cd.data[0] > SFF_8472_ID_LAST) printf("Unknown ID\n"); else printf("ID: %s\n", sff_8472_id[i2cd.data[0]]); bzero(&string, sizeof(string)); for (i = SFF_8472_VENDOR_START; i < SFF_8472_VENDOR_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_VENDOR_START] = i2cd.data[0]; } printf("Vendor %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_SN_START; i < SFF_8472_SN_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_SN_START] = i2cd.data[0]; } printf("SN %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_PN_START; i < SFF_8472_PN_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_PN_START] = i2cd.data[0]; } printf("PN %s\n", string); bzero(&string, sizeof(string)); for (i = SFF_8472_REV_START; i < SFF_8472_REV_END; i++) { i2cd.offset = i; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; string[i - SFF_8472_REV_START] = i2cd.data[0]; } printf("Rev %s\n", string); i2cd.offset = SFF_8472_DIAG_TYPE; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; if ((char )i2cd.data[0] & (SFF_8472_DIAG_IMPL | SFF_8472_DIAG_INTERNAL)) { /* Switch to reading from the Diagnostic address. */ i2cd.dev_addr = SFF_8472_DIAG; i2cd.len = 1; i2cd.offset = SFF_8472_TEMP; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; temp = i2cd.data[0] << 8; printf("Temp: "); if ((temp & SFF_8472_TEMP_SIGN) == SFF_8472_TEMP_SIGN) printf("-"); else printf("+"); printf("%dC\n", (temp & SFF_8472_TEMP_MSK) >> SFF_8472_TEMP_SHIFT); i2cd.offset = SFF_8472_VCC; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; vcc = i2cd.data[0] << 8; printf("Vcc %fV\n", vcc / SFF_8472_VCC_FACTOR); i2cd.offset = SFF_8472_TX_BIAS; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; tx_bias = i2cd.data[0] << 8; printf("TX Bias %fuA\n", tx_bias / SFF_8472_BIAS_FACTOR); i2cd.offset = SFF_8472_TX_POWER; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; tx_power = i2cd.data[0] << 8; printf("TX Power %fmW\n", tx_power / SFF_8472_POWER_FACTOR); i2cd.offset = SFF_8472_RX_POWER; if ((rc = doit(CHELSIO_T4_GET_I2C, &i2cd)) != 0) goto fail; rx_power = i2cd.data[0] << 8; printf("RX Power %fmW\n", rx_power / SFF_8472_POWER_FACTOR); } else printf("Diagnostics not supported.\n"); return(0); fail: if (rc == EPERM) warnx("No module/cable in port %ld", port); return (rc); } /* XXX: pass in a low/high and do range checks as well */ static int get_sched_param(const char *param, const char *args[], long *val) { char *p; if (strcmp(param, args[0]) != 0) return (EINVAL); p = str_to_number(args[1], val, NULL); if (*p) { warnx("parameter \"%s\" has bad value \"%s\"", args[0], args[1]); return (EINVAL); } return (0); } static int sched_class(int argc, const char *argv[]) { struct t4_sched_params op; int errs, i; memset(&op, 0xff, sizeof(op)); op.subcmd = -1; op.type = -1; if (argc == 0) { warnx("missing scheduling sub-command"); return (EINVAL); } if (!strcmp(argv[0], "config")) { op.subcmd = SCHED_CLASS_SUBCMD_CONFIG; op.u.config.minmax = -1; } else if (!strcmp(argv[0], "params")) { op.subcmd = SCHED_CLASS_SUBCMD_PARAMS; op.u.params.level = op.u.params.mode = op.u.params.rateunit = op.u.params.ratemode = op.u.params.channel = op.u.params.cl = op.u.params.minrate = op.u.params.maxrate = op.u.params.weight = op.u.params.pktsize = -1; } else { warnx("invalid scheduling sub-command \"%s\"", argv[0]); return (EINVAL); } /* Decode remaining arguments ... */ errs = 0; for (i = 1; i < argc; i += 2) { const char **args = &argv[i]; long l; if (i + 1 == argc) { warnx("missing argument for \"%s\"", args[0]); errs++; break; } if (!strcmp(args[0], "type")) { if (!strcmp(args[1], "packet")) op.type = SCHED_CLASS_TYPE_PACKET; else { warnx("invalid type parameter \"%s\"", args[1]); errs++; } continue; } if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { if(!get_sched_param("minmax", args, &l)) op.u.config.minmax = (int8_t)l; else { warnx("unknown scheduler config parameter " "\"%s\"", args[0]); errs++; } continue; } /* Rest applies only to SUBCMD_PARAMS */ if (op.subcmd != SCHED_CLASS_SUBCMD_PARAMS) continue; if (!strcmp(args[0], "level")) { if (!strcmp(args[1], "cl-rl")) op.u.params.level = SCHED_CLASS_LEVEL_CL_RL; else if (!strcmp(args[1], "cl-wrr")) op.u.params.level = SCHED_CLASS_LEVEL_CL_WRR; else if (!strcmp(args[1], "ch-rl")) op.u.params.level = SCHED_CLASS_LEVEL_CH_RL; else { warnx("invalid level parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "mode")) { if (!strcmp(args[1], "class")) op.u.params.mode = SCHED_CLASS_MODE_CLASS; else if (!strcmp(args[1], "flow")) op.u.params.mode = SCHED_CLASS_MODE_FLOW; else { warnx("invalid mode parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "rate-unit")) { if (!strcmp(args[1], "bits")) op.u.params.rateunit = SCHED_CLASS_RATEUNIT_BITS; else if (!strcmp(args[1], "pkts")) op.u.params.rateunit = SCHED_CLASS_RATEUNIT_PKTS; else { warnx("invalid rate-unit parameter \"%s\"", args[1]); errs++; } } else if (!strcmp(args[0], "rate-mode")) { if (!strcmp(args[1], "relative")) op.u.params.ratemode = SCHED_CLASS_RATEMODE_REL; else if (!strcmp(args[1], "absolute")) op.u.params.ratemode = SCHED_CLASS_RATEMODE_ABS; else { warnx("invalid rate-mode parameter \"%s\"", args[1]); errs++; } } else if (!get_sched_param("channel", args, &l)) op.u.params.channel = (int8_t)l; else if (!get_sched_param("class", args, &l)) op.u.params.cl = (int8_t)l; else if (!get_sched_param("min-rate", args, &l)) op.u.params.minrate = (int32_t)l; else if (!get_sched_param("max-rate", args, &l)) op.u.params.maxrate = (int32_t)l; else if (!get_sched_param("weight", args, &l)) op.u.params.weight = (int16_t)l; else if (!get_sched_param("pkt-size", args, &l)) op.u.params.pktsize = (int16_t)l; else { warnx("unknown scheduler parameter \"%s\"", args[0]); errs++; } } /* * Catch some logical fallacies in terms of argument combinations here * so we can offer more than just the EINVAL return from the driver. * The driver will be able to catch a lot more issues since it knows * the specifics of the device hardware capabilities like how many * channels, classes, etc. the device supports. */ if (op.type < 0) { warnx("sched \"type\" parameter missing"); errs++; } if (op.subcmd == SCHED_CLASS_SUBCMD_CONFIG) { if (op.u.config.minmax < 0) { warnx("sched config \"minmax\" parameter missing"); errs++; } } if (op.subcmd == SCHED_CLASS_SUBCMD_PARAMS) { if (op.u.params.level < 0) { warnx("sched params \"level\" parameter missing"); errs++; } if (op.u.params.mode < 0) { warnx("sched params \"mode\" parameter missing"); errs++; } if (op.u.params.rateunit < 0) { warnx("sched params \"rate-unit\" parameter missing"); errs++; } if (op.u.params.ratemode < 0) { warnx("sched params \"rate-mode\" parameter missing"); errs++; } if (op.u.params.channel < 0) { warnx("sched params \"channel\" missing"); errs++; } if (op.u.params.cl < 0) { warnx("sched params \"class\" missing"); errs++; } if (op.u.params.maxrate < 0 && (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { warnx("sched params \"max-rate\" missing for " "rate-limit level"); errs++; } if (op.u.params.weight < 0 && op.u.params.level == SCHED_CLASS_LEVEL_CL_WRR) { warnx("sched params \"weight\" missing for " "weighted-round-robin level"); errs++; } if (op.u.params.pktsize < 0 && (op.u.params.level == SCHED_CLASS_LEVEL_CL_RL || op.u.params.level == SCHED_CLASS_LEVEL_CH_RL)) { warnx("sched params \"pkt-size\" missing for " "rate-limit level"); errs++; } if (op.u.params.mode == SCHED_CLASS_MODE_FLOW && op.u.params.ratemode != SCHED_CLASS_RATEMODE_ABS) { warnx("sched params mode flow needs rate-mode absolute"); errs++; } if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_REL && !in_range(op.u.params.maxrate, 1, 100)) { warnx("sched params \"max-rate\" takes " "percentage value(1-100) for rate-mode relative"); errs++; } if (op.u.params.ratemode == SCHED_CLASS_RATEMODE_ABS && !in_range(op.u.params.maxrate, 1, 100000000)) { warnx("sched params \"max-rate\" takes " "value(1-100000000) for rate-mode absolute"); errs++; } if (op.u.params.maxrate > 0 && op.u.params.maxrate < op.u.params.minrate) { warnx("sched params \"max-rate\" is less than " "\"min-rate\""); errs++; } } if (errs > 0) { warnx("%d error%s in sched-class command", errs, errs == 1 ? "" : "s"); return (EINVAL); } return doit(CHELSIO_T4_SCHED_CLASS, &op); } static int sched_queue(int argc, const char *argv[]) { struct t4_sched_queue op = {0}; char *p; long val; if (argc != 3) { /* need " */ warnx("incorrect number of arguments."); return (EINVAL); } p = str_to_number(argv[0], &val, NULL); if (*p || val > UCHAR_MAX) { warnx("invalid port id \"%s\"", argv[0]); return (EINVAL); } op.port = (uint8_t)val; if (!strcmp(argv[1], "all") || !strcmp(argv[1], "*")) op.queue = -1; else { p = str_to_number(argv[1], &val, NULL); if (*p || val < -1) { warnx("invalid queue \"%s\"", argv[1]); return (EINVAL); } op.queue = (int8_t)val; } if (!strcmp(argv[2], "unbind") || !strcmp(argv[2], "clear")) op.cl = -1; else { p = str_to_number(argv[2], &val, NULL); if (*p || val < -1) { warnx("invalid class \"%s\"", argv[2]); return (EINVAL); } op.cl = (int8_t)val; } return doit(CHELSIO_T4_SCHED_QUEUE, &op); } static int run_cmd(int argc, const char *argv[]) { int rc = -1; const char *cmd = argv[0]; /* command */ argc--; argv++; if (!strcmp(cmd, "reg") || !strcmp(cmd, "reg32")) rc = register_io(argc, argv, 4); else if (!strcmp(cmd, "reg64")) rc = register_io(argc, argv, 8); else if (!strcmp(cmd, "regdump")) rc = dump_regs(argc, argv); else if (!strcmp(cmd, "filter")) rc = filter_cmd(argc, argv); else if (!strcmp(cmd, "context")) rc = get_sge_context(argc, argv); else if (!strcmp(cmd, "loadfw")) rc = loadfw(argc, argv); else if (!strcmp(cmd, "memdump")) rc = memdump(argc, argv); else if (!strcmp(cmd, "tcb")) rc = read_tcb(argc, argv); else if (!strcmp(cmd, "i2c")) rc = read_i2c(argc, argv); else if (!strcmp(cmd, "clearstats")) rc = clearstats(argc, argv); else if (!strcmp(cmd, "tracer")) rc = tracer_cmd(argc, argv); else if (!strcmp(cmd, "modinfo")) rc = modinfo(argc, argv); else if (!strcmp(cmd, "sched-class")) rc = sched_class(argc, argv); else if (!strcmp(cmd, "sched-queue")) rc = sched_queue(argc, argv); else if (!strcmp(cmd, "loadcfg")) rc = loadcfg(argc, argv); else if (!strcmp(cmd, "loadboot")) rc = loadboot(argc, argv); else if (!strcmp(cmd, "loadboot-cfg")) rc = loadbootcfg(argc, argv); + else if (!strcmp(cmd, "dumpstate")) + rc = dumpstate(argc, argv); else { rc = EINVAL; warnx("invalid command \"%s\"", cmd); } return (rc); } #define MAX_ARGS 15 static int run_cmd_loop(void) { int i, rc = 0; char buffer[128], *buf; const char *args[MAX_ARGS + 1]; /* * Simple loop: displays a "> " prompt and processes any input as a * cxgbetool command. You're supposed to enter only the part after * "cxgbetool t4nexX". Use "quit" or "exit" to exit. */ for (;;) { fprintf(stdout, "> "); fflush(stdout); buf = fgets(buffer, sizeof(buffer), stdin); if (buf == NULL) { if (ferror(stdin)) { warn("stdin error"); rc = errno; /* errno from fgets */ } break; } i = 0; while ((args[i] = strsep(&buf, " \t\n")) != NULL) { if (args[i][0] != 0 && ++i == MAX_ARGS) break; } args[i] = 0; if (i == 0) continue; /* skip empty line */ if (!strcmp(args[0], "quit") || !strcmp(args[0], "exit")) break; rc = run_cmd(i, args); } /* rc normally comes from the last command (not including quit/exit) */ return (rc); } int main(int argc, const char *argv[]) { int rc = -1; progname = argv[0]; if (argc == 2) { if (!strcmp(argv[1], "-h") || !strcmp(argv[1], "--help")) { usage(stdout); exit(0); } } if (argc < 3) { usage(stderr); exit(EINVAL); } nexus = argv[1]; /* progname and nexus */ argc -= 2; argv += 2; if (argc == 1 && !strcmp(argv[0], "stdio")) rc = run_cmd_loop(); else rc = run_cmd(argc, argv); return (rc); } Index: projects/make-check-sandbox =================================================================== --- projects/make-check-sandbox (revision 322021) +++ projects/make-check-sandbox (revision 322022) Property changes on: projects/make-check-sandbox ___________________________________________________________________ Modified: svn:mergeinfo ## -0,0 +0,1 ## Merged /head:r321994-322021