diff options
author | sjg <sjg@FreeBSD.org> | 2013-09-05 20:18:59 +0000 |
---|---|---|
committer | sjg <sjg@FreeBSD.org> | 2013-09-05 20:18:59 +0000 |
commit | 62bb1062226d3ce6a2350808256a25508978352d (patch) | |
tree | 22b131dceb13c3df96da594fbaadb693504797c7 /tools | |
parent | 72ab90509b3a51ab361bf710338f2ef44a4e360d (diff) | |
parent | 04932445481c2cb89ff69a83b961bdef3d64757e (diff) | |
download | FreeBSD-src-62bb1062226d3ce6a2350808256a25508978352d.zip FreeBSD-src-62bb1062226d3ce6a2350808256a25508978352d.tar.gz |
Merge from head
Diffstat (limited to 'tools')
165 files changed, 8659 insertions, 957 deletions
diff --git a/tools/build/mk/OptionalObsoleteFiles.inc b/tools/build/mk/OptionalObsoleteFiles.inc index b464c98..633ead0 100644 --- a/tools/build/mk/OptionalObsoleteFiles.inc +++ b/tools/build/mk/OptionalObsoleteFiles.inc @@ -206,7 +206,9 @@ OLD_FILES+=usr/share/man/man8/auditd.8.gz .if ${MK_AUTHPF} == no OLD_FILES+=usr/sbin/authpf +OLD_FILES+=usr/sbin/authpf-noip OLD_FILES+=usr/share/man/man8/authpf.8.gz +OLD_FILES+=usr/share/man/man8/authpf-noip.8.gz .endif .if ${MK_BIND} == no @@ -388,6 +390,9 @@ OLD_FILES+=var/named/etc/namedb/PROTO.localhost.rev OLD_FILES+=var/named/etc/namedb/make-localhost #OLD_FILES+=var/named/etc/namedb/named.conf # intentionally left out OLD_FILES+=var/named/etc/namedb/named.root +OLD_FILES+=var/named/etc/namedb/master/empty.db +OLD_FILES+=var/named/etc/namedb/master/localhost-forward.db +OLD_FILES+=var/named/etc/namedb/master/localhost-reverse.db OLD_DIRS+=var/named/etc/namedb/slave OLD_DIRS+=var/named/etc/namedb/master OLD_DIRS+=var/named/etc/namedb/dynamic @@ -786,6 +791,38 @@ OLD_FILES+=usr/include/clang/3.2/x86intrin.h OLD_FILES+=usr/include/clang/3.2/xmmintrin.h OLD_FILES+=usr/include/clang/3.2/xopintrin.h OLD_DIRS+=usr/include/clang/3.2 +OLD_FILES+=usr/include/clang/3.3/__wmmintrin_aes.h +OLD_FILES+=usr/include/clang/3.3/__wmmintrin_pclmul.h +OLD_FILES+=usr/include/clang/3.3/altivec.h +OLD_FILES+=usr/include/clang/3.3/ammintrin.h +OLD_FILES+=usr/include/clang/3.3/avx2intrin.h +OLD_FILES+=usr/include/clang/3.3/avxintrin.h +OLD_FILES+=usr/include/clang/3.3/bmi2intrin.h +OLD_FILES+=usr/include/clang/3.3/bmiintrin.h +OLD_FILES+=usr/include/clang/3.3/cpuid.h +OLD_FILES+=usr/include/clang/3.3/emmintrin.h +OLD_FILES+=usr/include/clang/3.3/f16cintrin.h +OLD_FILES+=usr/include/clang/3.3/fma4intrin.h +OLD_FILES+=usr/include/clang/3.3/fmaintrin.h +OLD_FILES+=usr/include/clang/3.3/immintrin.h +OLD_FILES+=usr/include/clang/3.3/lzcntintrin.h +OLD_FILES+=usr/include/clang/3.3/mm3dnow.h +OLD_FILES+=usr/include/clang/3.3/mm_malloc.h +OLD_FILES+=usr/include/clang/3.3/mmintrin.h +OLD_FILES+=usr/include/clang/3.3/module.map +OLD_FILES+=usr/include/clang/3.3/nmmintrin.h +OLD_FILES+=usr/include/clang/3.3/pmmintrin.h +OLD_FILES+=usr/include/clang/3.3/popcntintrin.h +OLD_FILES+=usr/include/clang/3.3/prfchwintrin.h +OLD_FILES+=usr/include/clang/3.3/rdseedintrin.h +OLD_FILES+=usr/include/clang/3.3/rtmintrin.h +OLD_FILES+=usr/include/clang/3.3/smmintrin.h +OLD_FILES+=usr/include/clang/3.3/tmmintrin.h +OLD_FILES+=usr/include/clang/3.3/wmmintrin.h +OLD_FILES+=usr/include/clang/3.3/x86intrin.h +OLD_FILES+=usr/include/clang/3.3/xmmintrin.h +OLD_FILES+=usr/include/clang/3.3/xopintrin.h +OLD_DIRS+=usr/include/clang/3.3 OLD_DIRS+=usr/include/clang OLD_FILES+=usr/share/doc/llvm/clang/LICENSE.TXT OLD_DIRS+=usr/share/doc/llvm/clang @@ -857,35 +894,6 @@ OLD_FILES+=usr/share/man/man1/ctm_smail.1.gz OLD_FILES+=usr/share/man/man5/ctm.5.gz .endif -.if ${MK_CVS} == no -OLD_FILES+=usr/bin/cvs -OLD_FILES+=usr/bin/cvsbug -OLD_FILES+=usr/share/examples/cvs/contrib/README -OLD_FILES+=usr/share/examples/cvs/contrib/clmerge -OLD_FILES+=usr/share/examples/cvs/contrib/cln_hist -OLD_FILES+=usr/share/examples/cvs/contrib/commit_prep -OLD_FILES+=usr/share/examples/cvs/contrib/cvs2vendor -OLD_FILES+=usr/share/examples/cvs/contrib/cvs_acls -OLD_FILES+=usr/share/examples/cvs/contrib/cvscheck -OLD_FILES+=usr/share/examples/cvs/contrib/cvscheck.man -OLD_FILES+=usr/share/examples/cvs/contrib/cvshelp.man -OLD_FILES+=usr/share/examples/cvs/contrib/descend.man -OLD_FILES+=usr/share/examples/cvs/contrib/easy-import -OLD_FILES+=usr/share/examples/cvs/contrib/intro.doc -OLD_FILES+=usr/share/examples/cvs/contrib/log -OLD_FILES+=usr/share/examples/cvs/contrib/log_accum -OLD_FILES+=usr/share/examples/cvs/contrib/mfpipe -OLD_FILES+=usr/share/examples/cvs/contrib/rcs-to-cvs -OLD_FILES+=usr/share/examples/cvs/contrib/rcs2log -OLD_FILES+=usr/share/examples/cvs/contrib/rcslock -OLD_FILES+=usr/share/examples/cvs/contrib/sccs2rcs -OLD_FILES+=usr/share/info/cvs.info.gz -OLD_FILES+=usr/share/info/cvsclient.info.gz -OLD_FILES+=usr/share/man/man1/cvs.1.gz -OLD_FILES+=usr/share/man/man5/cvs.5.gz -OLD_FILES+=usr/share/man/man8/cvsbug.8.gz -.endif - # devd(8) and gperf(1) not listed here on purpose .if ${MK_CXX} == no OLD_FILES+=usr/bin/CC @@ -1484,6 +1492,7 @@ OLD_FILES+=usr/share/man/man8/fdcontrol.8.gz OLD_FILES+=etc/freebsd-update.conf OLD_FILES+=usr/sbin/freebsd-update OLD_FILES+=usr/share/examples/etc/freebsd-update.conf +OLD_FILES+=usr/share/man/man5/freebsd-update.conf.5.gz OLD_FILES+=usr/share/man/man8/freebsd-update.8.gz .endif @@ -1549,6 +1558,7 @@ OLD_FILES+=usr/include/gcc/4.2/mmintrin.h OLD_FILES+=usr/include/gcc/4.2/pmmintrin.h OLD_FILES+=usr/include/gcc/4.2/tmmintrin.h OLD_FILES+=usr/include/gcc/4.2/xmmintrin.h +OLD_FILES+=usr/include/gcc/4.2/mm3dnow.h .elif ${TARGET_ARCH} == "ia64" OLD_FILES+=usr/include/gcc/4.2/ia64intrin.h .elif ${TARGET_ARCH} == "arm" @@ -2188,8 +2198,25 @@ OLD_FILES+=usr/share/man/man5/hesiod.conf.5.gz # to be filled in #.endif -.if ${MK_IDEA} == no -OLD_FILES+=usr/include/openssl/idea.h +.if ${MK_ICONV} == no +OLD_FILES+=usr/bin/iconv +OLD_FILES+=usr/bin/mkcsmapper +OLD_FILES+=usr/bin/mkesdb +OLD_FILES+=usr/include/_libiconv_compat.h +OLD_FILES+=usr/include/iconv.h +OLD_FILES+=usr/share/man/man1/iconv.1.gz +OLD_FILES+=usr/share/man/man1/mkcsmapper.1.gz +OLD_FILES+=usr/share/man/man1/mkesdb.1.gz +OLD_FILES+=usr/share/man/man3/__iconv.3.gz +OLD_FILES+=usr/share/man/man3/__iconv_free_list.3.gz +OLD_FILES+=usr/share/man/man3/__iconv_get_list.3.gz +OLD_FILES+=usr/share/man/man3/iconv.3.gz +OLD_FILES+=usr/share/man/man3/iconv_canonicalize.3.gz +OLD_FILES+=usr/share/man/man3/iconv_close.3.gz +OLD_FILES+=usr/share/man/man3/iconv_open.3.gz +OLD_FILES+=usr/share/man/man3/iconv_open_into.3.gz +OLD_FILES+=usr/share/man/man3/iconvctl.3.gz +OLD_FILES+=usr/share/man/man3/iconvlist.3.gz .endif .if ${MK_INET6} == no @@ -3332,6 +3359,13 @@ OLD_FILES+=usr/share/man/man8/verify_krb5_conf.8.gz # to be filled in #.endif +.if ${MK_LIBICONV_COMPAT} == no +OLD_FILES+=usr/lib/libiconv.a +OLD_FILES+=usr/lib/libiconv.so +OLD_FILES+=usr/lib/libiconv.so.3 +OLD_FILES+=usr/lib/libiconv_p.a +.endif + .if ${MK_LIBCPLUSPLUS} == no OLD_LIBS+=lib/libcxxrt.so.1 OLD_FILES+=usr/lib/libc++.a @@ -3646,9 +3680,9 @@ OLD_FILES+=usr/share/man/man8/ntptime.8.gz # to be filled in #.endif -#.if ${MK_OPENSSH} == no -# to be filled in -#.endif +.if ${MK_OPENSSH} == no +OLD_FILES+=usr.bin/ssh-copy-id +.endif #.if ${MK_OPENSSL} == no # to be filled in @@ -3989,7 +4023,6 @@ OLD_FILES+=usr/share/man/man8/rtquery.8.gz .if ${MK_SENDMAIL} == no OLD_FILES+=etc/periodic/daily/150.clean-hoststat -OLD_FILES+=etc/periodic/daily/210.backup-aliases OLD_FILES+=etc/periodic/daily/440.status-mailq OLD_FILES+=etc/periodic/daily/460.status-mail-rejects OLD_FILES+=etc/periodic/daily/500.queuerun @@ -4318,3 +4351,27 @@ OLD_FILES+=usr/share/man/man8/wpa_cli.8.gz OLD_FILES+=usr/share/man/man8/wpa_passphrase.8.gz OLD_FILES+=usr/share/man/man8/wpa_supplicant.8.gz .endif + +.if ${MK_SVNLITE} == no || ${MK_SVN} == yes +OLD_FILES+=usr/bin/svnlite +OLD_FILES+=usr/bin/svnliteadmin +OLD_FILES+=usr/bin/svnlitedumpfilter +OLD_FILES+=usr/bin/svnlitelook +OLD_FILES+=usr/bin/svnlitemucc +OLD_FILES+=usr/bin/svnliterdump +OLD_FILES+=usr/bin/svnliteserve +OLD_FILES+=usr/bin/svnlitesync +OLD_FILES+=usr/bin/svnliteversion +.endif + +.if ${MK_SVN} == no +OLD_FILES+=usr/bin/svn +OLD_FILES+=usr/bin/svnadmin +OLD_FILES+=usr/bin/svndumpfilter +OLD_FILES+=usr/bin/svnlook +OLD_FILES+=usr/bin/svnmucc +OLD_FILES+=usr/bin/svnrdump +OLD_FILES+=usr/bin/svnserve +OLD_FILES+=usr/bin/svnsync +OLD_FILES+=usr/bin/svnversion +.endif diff --git a/tools/build/options/WITHOUT_ARM_EABI b/tools/build/options/WITHOUT_ARM_EABI new file mode 100644 index 0000000..58e8348 --- /dev/null +++ b/tools/build/options/WITHOUT_ARM_EABI @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set the ARM ABI to OABI. diff --git a/tools/build/options/WITH_BMAKE b/tools/build/options/WITHOUT_BMAKE index 2b47121..ab3cece 100644 --- a/tools/build/options/WITH_BMAKE +++ b/tools/build/options/WITHOUT_BMAKE @@ -1,5 +1,5 @@ .\" $FreeBSD$ -Build and install the portable BSD make (bmake) as +Set to not build and install the portable BSD make (bmake) as .Xr make 1 instead of the traditional FreeBSD make. This build option is temporary. diff --git a/tools/build/options/WITHOUT_CROSS_COMPILER b/tools/build/options/WITHOUT_CROSS_COMPILER new file mode 100644 index 0000000..1ded25b --- /dev/null +++ b/tools/build/options/WITHOUT_CROSS_COMPILER @@ -0,0 +1,3 @@ +.\" $FreeBSD$ +Set to not build a cross compiler in the cross-tools stage of +buildworld, buildkernel, etc. diff --git a/tools/build/options/WITHOUT_FORMAT_EXTENSIONS b/tools/build/options/WITHOUT_FORMAT_EXTENSIONS new file mode 100644 index 0000000..7ae02e1 --- /dev/null +++ b/tools/build/options/WITHOUT_FORMAT_EXTENSIONS @@ -0,0 +1,5 @@ +.\" $FreeBSD$ +Set to not enable +.Fl fformat-extensions +when compiling the kernel. +Also disables all format checking. diff --git a/tools/build/options/WITHOUT_ICONV b/tools/build/options/WITHOUT_ICONV new file mode 100644 index 0000000..a43dd3a --- /dev/null +++ b/tools/build/options/WITHOUT_ICONV @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to not build iconv as part of libc. diff --git a/tools/build/options/WITHOUT_JAIL b/tools/build/options/WITHOUT_JAIL index 27774e8..355b716 100644 --- a/tools/build/options/WITHOUT_JAIL +++ b/tools/build/options/WITHOUT_JAIL @@ -1,3 +1,3 @@ .\" $FreeBSD$ -Set to not build tools for the support of jails; e.g. +Set to not build tools for the support of jails; e.g., .Xr jail 8 . diff --git a/tools/build/options/WITHOUT_KERBEROS_SUPPORT b/tools/build/options/WITHOUT_KERBEROS_SUPPORT index a724fbf..e8dd495 100644 --- a/tools/build/options/WITHOUT_KERBEROS_SUPPORT +++ b/tools/build/options/WITHOUT_KERBEROS_SUPPORT @@ -1,6 +1,5 @@ .\" $FreeBSD$ Set to build some programs without Kerberos support, like -.Xr cvs 1 , .Xr ssh 1 , .Xr telnet 1 , .Xr sshd 8 , diff --git a/tools/build/options/WITHOUT_LEGACY_CONSOLE b/tools/build/options/WITHOUT_LEGACY_CONSOLE index 85e8604..8f21d1e 100644 --- a/tools/build/options/WITHOUT_LEGACY_CONSOLE +++ b/tools/build/options/WITHOUT_LEGACY_CONSOLE @@ -1,5 +1,5 @@ .\" $FreeBSD$ -Set to not build programs that support a legacy PC console; e.g. +Set to not build programs that support a legacy PC console; e.g., .Xr kbdcontrol 8 and .Xr vidcontrol 8 . diff --git a/tools/build/options/WITHOUT_PKGTOOLS b/tools/build/options/WITHOUT_SVNLITE index a1c7c56..61b66dc 100644 --- a/tools/build/options/WITHOUT_PKGTOOLS +++ b/tools/build/options/WITHOUT_SVNLITE @@ -1,4 +1,4 @@ .\" $FreeBSD$ Set to not build -.Xr pkg_add 8 +.Xr svnlite 1 and related programs. diff --git a/tools/build/options/WITH_ARM_EABI b/tools/build/options/WITH_ARM_EABI deleted file mode 100644 index dba6e5f..0000000 --- a/tools/build/options/WITH_ARM_EABI +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Set the ARM ABI to EABI. diff --git a/tools/build/options/WITH_BSDCONFIG b/tools/build/options/WITH_BSDCONFIG deleted file mode 100644 index f3e6e25..0000000 --- a/tools/build/options/WITH_BSDCONFIG +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Set to install bsdconfig(8), a BSD-licensed configuration/management utility. diff --git a/tools/build/options/WITH_BSD_PATCH b/tools/build/options/WITH_BSD_PATCH deleted file mode 100644 index 8430d2a..0000000 --- a/tools/build/options/WITH_BSD_PATCH +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Install BSD-licensed patch as 'patch' instead of GNU patch. diff --git a/tools/build/options/WITH_DEBUG_FILES b/tools/build/options/WITH_DEBUG_FILES new file mode 100644 index 0000000..16eee2a --- /dev/null +++ b/tools/build/options/WITH_DEBUG_FILES @@ -0,0 +1,7 @@ +.\" $FreeBSD$ +Set to strip debug info into a separate file for each executable binary +and shared library. +The debug files will be placed in a subdirectory of +.Pa /usr/lib/debug +and are located automatically by +.Xr gdb 1 . diff --git a/tools/build/options/WITH_ICONV b/tools/build/options/WITH_ICONV deleted file mode 100644 index 7acbe44..0000000 --- a/tools/build/options/WITH_ICONV +++ /dev/null @@ -1,2 +0,0 @@ -.\" $FreeBSD$ -Set to build iconv as part of libc. diff --git a/tools/build/options/WITH_IDEA b/tools/build/options/WITH_IDEA deleted file mode 100644 index 785dfc6..0000000 --- a/tools/build/options/WITH_IDEA +++ /dev/null @@ -1,6 +0,0 @@ -.\" $FreeBSD$ -Set to build the IDEA encryption code. -This code is patented in the USA and many European countries. -It is -.Em "YOUR RESPONSIBILITY" -to determine if you can legally use IDEA. diff --git a/tools/build/options/WITH_LIBICONV_COMPAT b/tools/build/options/WITH_LIBICONV_COMPAT new file mode 100644 index 0000000..f414798 --- /dev/null +++ b/tools/build/options/WITH_LIBICONV_COMPAT @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to build libiconv API and link time compatibility. diff --git a/tools/build/options/WITH_PKGTOOLS b/tools/build/options/WITH_PKGTOOLS new file mode 100644 index 0000000..0c09224 --- /dev/null +++ b/tools/build/options/WITH_PKGTOOLS @@ -0,0 +1,4 @@ +.\" $FreeBSD$ +Set to build +.Xr pkg_add 8 +and related programs. diff --git a/tools/build/options/WITH_SVN b/tools/build/options/WITH_SVN new file mode 100644 index 0000000..829a3a7 --- /dev/null +++ b/tools/build/options/WITH_SVN @@ -0,0 +1,5 @@ +.\" $FreeBSD$ +Set to install +.Xr svnlite 1 +as +.Xr svn 1 . diff --git a/tools/build/options/WITH_USB_GADGET_EXAMPLES b/tools/build/options/WITH_USB_GADGET_EXAMPLES new file mode 100644 index 0000000..2ecbdb7 --- /dev/null +++ b/tools/build/options/WITH_USB_GADGET_EXAMPLES @@ -0,0 +1,2 @@ +.\" $FreeBSD$ +Set to build USB gadget kernel modules. diff --git a/tools/build/options/makeman b/tools/build/options/makeman index 61c0776..cb4d946 100755 --- a/tools/build/options/makeman +++ b/tools/build/options/makeman @@ -3,6 +3,7 @@ # This file is in the public domain. set -o errexit +LC_ALL=C ident='$FreeBSD$' @@ -198,7 +199,12 @@ that can be used for source builds. .Bl -tag -width indent EOF show settings SRCCONF=/dev/null | sort > $t/config_default - show with SRCCONF=/dev/null | sort > $t/config_WITH_ALL + # Work around WITH_LDNS_UTILS forcing BIND_UTILS off by parsing the + # actual config that results from enabling every WITH_ option. This + # can be reverted if/when we no longer have options that disable + # others. + show with SRCCONF=/dev/null | sort | sed 's/$/=/' > $t/src.conf + show settings SRCCONF=$t/src.conf | sort > $t/config_WITH_ALL show without SRCCONF=/dev/null | sort > $t/config_WITHOUT_ALL show_options | @@ -229,6 +235,18 @@ EOF exit 1 fi + show settings SRCCONF=/dev/null -D${opt} | sort > $t/config_${opt} + comm -13 $t/config_default $t/config_${opt} | sed -n "/^${opt}$/!p" | + comm -13 $t/deps - > $t/deps2 + + # Work around BIND_UTILS=no being the default when every WITH_ + # option is enabled. + if [ "$(cat $t/deps2)" = WITHOUT_BIND_UTILS ]; then + sort $t/deps $t/deps2 > $t/_deps + mv $t/_deps $t/deps + :> $t/deps2 + fi + if [ -s $t/deps ] ; then echo 'When set, it also enforces the following options:' echo '.Pp' @@ -240,10 +258,6 @@ EOF echo '.El' fi - show settings SRCCONF=/dev/null -D${opt} | sort > $t/config_${opt} - comm -13 $t/config_default $t/config_${opt} | sed -n "/^${opt}$/!p" | - comm -13 $t/deps - > $t/deps2 - if [ -s $t/deps2 ] ; then if [ -s $t/deps ] ; then echo '.Pp' diff --git a/tools/regression/aio/aiop/aiop.c b/tools/regression/aio/aiop/aiop.c index 31a977e..3e64dbe 100644 --- a/tools/regression/aio/aiop/aiop.c +++ b/tools/regression/aio/aiop/aiop.c @@ -39,6 +39,7 @@ #include <sys/cdefs.h> __FBSDID("$FreeBSD$"); +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <unistd.h> @@ -186,7 +187,7 @@ main(int argc, char *argv[]) perror("unknown file type\n"); exit(1); } - printf("File: %s; File size %qd bytes\n", fn, file_size); + printf("File: %s; File size %jd bytes\n", fn, (intmax_t)file_size); aio = calloc(aio_len, sizeof(struct aiocb)); abuf = calloc(aio_len, sizeof(char *)); diff --git a/tools/regression/aio/aiotest/aiotest.c b/tools/regression/aio/aiotest/aiotest.c index 60de273..48c7aba 100644 --- a/tools/regression/aio/aiotest/aiotest.c +++ b/tools/regression/aio/aiotest/aiotest.c @@ -49,6 +49,7 @@ #include <fcntl.h> #include <libutil.h> #include <limits.h> +#include <stdint.h> #include <stdio.h> #include <stdlib.h> #include <string.h> @@ -269,7 +270,7 @@ aio_write_test(struct aio_context *ac) if (len != ac->ac_buflen) { aio_cleanup(ac); errx(-1, "FAIL: %s: aio_write_test: aio_waitcomplete: short " - "write (%d)", ac->ac_test, len); + "write (%jd)", ac->ac_test, (intmax_t)len); } } @@ -329,7 +330,7 @@ aio_read_test(struct aio_context *ac) if (len != ac->ac_buflen) { aio_cleanup(ac); errx(-1, "FAIL: %s: aio_read_test: aio_waitcomplete: short " - "read (%d)", ac->ac_test, len); + "read (%jd)", ac->ac_test, (intmax_t)len); } if (aio_test_buffer(ac->ac_buffer, ac->ac_buflen, ac->ac_seed) == 0) { @@ -366,7 +367,7 @@ aio_file_cleanup(void *arg) #define FILE_LEN GLOBAL_MAX #define FILE_TIMEOUT 30 -static int +static void aio_file_test(void) { char pathname[PATH_MAX]; @@ -414,7 +415,7 @@ aio_fifo_cleanup(void *arg) #define FIFO_LEN 256 #define FIFO_TIMEOUT 30 -static int +static void aio_fifo_test(void) { int error, read_fd = -1, write_fd = -1; @@ -481,7 +482,7 @@ aio_unix_socketpair_cleanup(void *arg) #define UNIX_SOCKETPAIR_LEN 256 #define UNIX_SOCKETPAIR_TIMEOUT 30 -static int +static void aio_unix_socketpair_test(void) { struct aio_unix_socketpair_arg arg; @@ -515,13 +516,14 @@ aio_pty_cleanup(void *arg) { struct aio_pty_arg *apa; + apa = arg; close(apa->apa_read_fd); close(apa->apa_write_fd); }; #define PTY_LEN 256 #define PTY_TIMEOUT 30 -static int +static void aio_pty_test(void) { struct aio_pty_arg arg; @@ -573,7 +575,7 @@ aio_pipe_cleanup(void *arg) #define PIPE_LEN 256 #define PIPE_TIMEOUT 30 -static int +static void aio_pipe_test(void) { struct aio_context ac; @@ -628,7 +630,7 @@ aio_md_cleanup(void *arg) #define MD_LEN GLOBAL_MAX #define MD_TIMEOUT 30 -static int +static void aio_md_test(void) { int error, fd, i, mdctl_fd, unit; diff --git a/tools/regression/bin/sh/builtins/alias4.0 b/tools/regression/bin/sh/builtins/alias4.0 new file mode 100644 index 0000000..3d5efec --- /dev/null +++ b/tools/regression/bin/sh/builtins/alias4.0 @@ -0,0 +1,4 @@ +# $FreeBSD$ + +unalias -a +alias -- diff --git a/tools/regression/bin/sh/builtins/break4.4 b/tools/regression/bin/sh/builtins/break4.4 new file mode 100644 index 0000000..d52ff52 --- /dev/null +++ b/tools/regression/bin/sh/builtins/break4.4 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +# Although this is not specified by POSIX, some configure scripts (gawk 4.1.0) +# appear to depend on it. + +break +exit 4 diff --git a/tools/regression/bin/sh/builtins/break5.4 b/tools/regression/bin/sh/builtins/break5.4 new file mode 100644 index 0000000..7df8e18 --- /dev/null +++ b/tools/regression/bin/sh/builtins/break5.4 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +# Although this is not specified by POSIX, some configure scripts (gawk 4.1.0) +# appear to depend on it. +# In some uncommitted code, the subshell environment corrupted the outer +# shell environment's state. + +(for i in a b c; do + exit 3 +done) +break +exit 4 diff --git a/tools/regression/bin/sh/builtins/jobid1.0 b/tools/regression/bin/sh/builtins/jobid1.0 new file mode 100644 index 0000000..483fda2 --- /dev/null +++ b/tools/regression/bin/sh/builtins/jobid1.0 @@ -0,0 +1,7 @@ +# $FreeBSD$ +# Non-standard builtin. + +: & +p1=$! +p2=$(jobid) +[ "${p1:?}" = "${p2:?}" ] diff --git a/tools/regression/bin/sh/builtins/jobid2.0 b/tools/regression/bin/sh/builtins/jobid2.0 new file mode 100644 index 0000000..101831a --- /dev/null +++ b/tools/regression/bin/sh/builtins/jobid2.0 @@ -0,0 +1,9 @@ +# $FreeBSD$ + +: & +p1=$(jobid) +p2=$(jobid --) +p3=$(jobid %+) +p4=$(jobid -- %+) +[ "${p1:?}" = "${p2:?}" ] && [ "${p2:?}" = "${p3:?}" ] && +[ "${p3:?}" = "${p4:?}" ] && [ "${p4:?}" = "${p1:?}" ] diff --git a/tools/regression/bin/sh/builtins/local2.0 b/tools/regression/bin/sh/builtins/local2.0 new file mode 100644 index 0000000..cc8c10f --- /dev/null +++ b/tools/regression/bin/sh/builtins/local2.0 @@ -0,0 +1,17 @@ +# $FreeBSD$ + +f() { + local - + set -a + case $- in + *a*) : ;; + *) echo In-function \$- bad + esac +} +case $- in +*a*) echo Initial \$- bad +esac +f +case $- in +*a*) echo Final \$- bad +esac diff --git a/tools/regression/bin/sh/builtins/local3.0 b/tools/regression/bin/sh/builtins/local3.0 new file mode 100644 index 0000000..39ee370 --- /dev/null +++ b/tools/regression/bin/sh/builtins/local3.0 @@ -0,0 +1,26 @@ +# $FreeBSD$ + +f() { + local "$@" + set -a + x=7 + case $- in + *a*) : ;; + *) echo In-function \$- bad + esac + [ "$x" = 7 ] || echo In-function \$x bad +} +x=1 +case $- in +*a*) echo Initial \$- bad +esac +f x - +case $- in +*a*) echo Intermediate \$- bad +esac +[ "$x" = 1 ] || echo Intermediate \$x bad +f - x +case $- in +*a*) echo Final \$- bad +esac +[ "$x" = 1 ] || echo Final \$x bad diff --git a/tools/regression/bin/sh/builtins/local4.0 b/tools/regression/bin/sh/builtins/local4.0 new file mode 100644 index 0000000..3955aaa --- /dev/null +++ b/tools/regression/bin/sh/builtins/local4.0 @@ -0,0 +1,12 @@ +# $FreeBSD$ + +f() { + local -- x + x=2 + [ "$x" = 2 ] +} +x=1 +f || exit 3 +[ "$x" = 1 ] || exit 3 +f || exit 3 +[ "$x" = 1 ] || exit 3 diff --git a/tools/regression/bin/sh/builtins/read7.0 b/tools/regression/bin/sh/builtins/read7.0 new file mode 100644 index 0000000..e78f887 --- /dev/null +++ b/tools/regression/bin/sh/builtins/read7.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ + +{ errmsg=`read x <&- 2>&1 >&3`; } 3>&1 +r=$? +[ "$r" -ge 2 ] && [ "$r" -le 128 ] && [ -n "$errmsg" ] diff --git a/tools/regression/bin/sh/builtins/return8.0 b/tools/regression/bin/sh/builtins/return8.0 new file mode 100644 index 0000000..f00e859 --- /dev/null +++ b/tools/regression/bin/sh/builtins/return8.0 @@ -0,0 +1,13 @@ +# $FreeBSD$ + +if [ "$1" = nested ]; then + return 17 +fi + +f() { + set -- nested + . "$0" + return $(($? ^ 1)) +} +f +exit $(($? ^ 16)) diff --git a/tools/regression/bin/sh/builtins/type3.0 b/tools/regression/bin/sh/builtins/type3.0 new file mode 100644 index 0000000..87cccdd --- /dev/null +++ b/tools/regression/bin/sh/builtins/type3.0 @@ -0,0 +1,3 @@ +# $FreeBSD$ + +[ "$(type type)" = "$(type -- type)" ] diff --git a/tools/regression/bin/sh/builtins/wait10.0 b/tools/regression/bin/sh/builtins/wait10.0 new file mode 100644 index 0000000..864fc78 --- /dev/null +++ b/tools/regression/bin/sh/builtins/wait10.0 @@ -0,0 +1,5 @@ +# $FreeBSD$ +# Init cannot be a child of the shell. +exit 49 & p49=$! +wait 1 "$p49" +[ "$?" = 49 ] diff --git a/tools/regression/bin/sh/builtins/wait8.0 b/tools/regression/bin/sh/builtins/wait8.0 new file mode 100644 index 0000000..b59ff59 --- /dev/null +++ b/tools/regression/bin/sh/builtins/wait8.0 @@ -0,0 +1,7 @@ +# $FreeBSD$ + +exit 44 & p44=$! +exit 45 & p45=$! +exit 7 & p7=$! +wait "$p44" "$p7" "$p45" +[ "$?" = 45 ] diff --git a/tools/regression/bin/sh/builtins/wait9.127 b/tools/regression/bin/sh/builtins/wait9.127 new file mode 100644 index 0000000..661f275 --- /dev/null +++ b/tools/regression/bin/sh/builtins/wait9.127 @@ -0,0 +1,3 @@ +# $FreeBSD$ +# Init cannot be a child of the shell. +wait 1 diff --git a/tools/regression/bin/sh/execution/int-cmd1.0 b/tools/regression/bin/sh/execution/int-cmd1.0 new file mode 100644 index 0000000..a1f097b --- /dev/null +++ b/tools/regression/bin/sh/execution/int-cmd1.0 @@ -0,0 +1,3 @@ +# $FreeBSD$ + +! echo echo bad | $SH -ic 'fi' 2>/dev/null diff --git a/tools/regression/bin/sh/expansion/arith13.0 b/tools/regression/bin/sh/expansion/arith13.0 new file mode 100644 index 0000000..207e488 --- /dev/null +++ b/tools/regression/bin/sh/expansion/arith13.0 @@ -0,0 +1,6 @@ +# $FreeBSD$ +# Pre-increment and pre-decrement in arithmetic expansion are not in POSIX. +# Require either an error or a correct implementation. + +! (eval 'x=4; [ $((++x)) != 5 ] || [ $x != 5 ]') 2>/dev/null && +! (eval 'x=2; [ $((--x)) != 1 ] || [ $x != 1 ]') 2>/dev/null diff --git a/tools/regression/bin/sh/parser/empty-cmd1.0 b/tools/regression/bin/sh/parser/empty-cmd1.0 new file mode 100644 index 0000000..f8b01e9 --- /dev/null +++ b/tools/regression/bin/sh/parser/empty-cmd1.0 @@ -0,0 +1,3 @@ +# $FreeBSD$ + +! (eval ': || f()') 2>/dev/null diff --git a/tools/regression/bin/sh/parser/only-redir2.0 b/tools/regression/bin/sh/parser/only-redir2.0 new file mode 100644 index 0000000..b9e9501 --- /dev/null +++ b/tools/regression/bin/sh/parser/only-redir2.0 @@ -0,0 +1,2 @@ +# $FreeBSD$ +</dev/null | : diff --git a/tools/regression/bin/sh/parser/only-redir3.0 b/tools/regression/bin/sh/parser/only-redir3.0 new file mode 100644 index 0000000..128a483 --- /dev/null +++ b/tools/regression/bin/sh/parser/only-redir3.0 @@ -0,0 +1,2 @@ +# $FreeBSD$ +case x in x) </dev/null ;; esac diff --git a/tools/regression/bin/sh/parser/only-redir4.0 b/tools/regression/bin/sh/parser/only-redir4.0 new file mode 100644 index 0000000..d804e12 --- /dev/null +++ b/tools/regression/bin/sh/parser/only-redir4.0 @@ -0,0 +1,2 @@ +# $FreeBSD$ +case x in x) </dev/null ;& esac diff --git a/tools/regression/bin/test/regress.sh b/tools/regression/bin/test/regress.sh index 117a7e2..9229551 100644 --- a/tools/regression/bin/test/regress.sh +++ b/tools/regression/bin/test/regress.sh @@ -52,7 +52,7 @@ t () } count=0 -echo "1..266" +echo "1..130" t 0 'b = b' t 0 'b == b' @@ -194,66 +194,3 @@ t 1 '\( ! -a \)' t 0 '\( -n -o \)' t 1 '\( -z -o \)' t 1 '\( ! -o \)' - -# Test all file timestamp comparison operators -s() { - t ${1} "${35} -nt ${36}" - t ${2} "${35} -ntaa ${36}" - t ${3} "${35} -ntab ${36}" - t ${4} "${35} -ntac ${36}" - t ${5} "${35} -ntam ${36}" - t ${6} "${35} -ntba ${36}" - t ${7} "${35} -ntbb ${36}" - t ${8} "${35} -ntbc ${36}" - t ${9} "${35} -ntbm ${36}" - t ${10} "${35} -ntca ${36}" - t ${11} "${35} -ntcb ${36}" - t ${12} "${35} -ntcc ${36}" - t ${13} "${35} -ntcm ${36}" - t ${14} "${35} -ntma ${36}" - t ${15} "${35} -ntmb ${36}" - t ${16} "${35} -ntmc ${36}" - t ${17} "${35} -ntmm ${36}" - t ${18} "${35} -ot ${36}" - t ${19} "${35} -otaa ${36}" - t ${20} "${35} -otab ${36}" - t ${21} "${35} -otac ${36}" - t ${22} "${35} -otam ${36}" - t ${23} "${35} -otba ${36}" - t ${24} "${35} -otbb ${36}" - t ${25} "${35} -otbc ${36}" - t ${26} "${35} -otbm ${36}" - t ${27} "${35} -otca ${36}" - t ${28} "${35} -otcb ${36}" - t ${29} "${35} -otcc ${36}" - t ${30} "${35} -otcm ${36}" - t ${31} "${35} -otma ${36}" - t ${32} "${35} -otmb ${36}" - t ${33} "${35} -otmc ${36}" - t ${34} "${35} -otmm ${36}" -} - -a=/tmp/test$$.1 -b=/tmp/test$$.2 -trap "rm -f $a $b" EXIT - -# Tests 131-164 -s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b - -touch $a -# Tests 165-198 -s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 $a $b - -sleep 2 # Ensure $b is newer than $a -touch $b -# Tests 199-232 -s 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 $a $b - -sleep 2 -echo >$b # Updates mtime & ctime -sleep 2 -touch -A 01 -a $b - -# $b now has ctime > mtime > atime > btime -# Tests 233-266 -s 1 1 0 1 1 1 1 1 1 0 0 1 0 0 0 1 1 1 1 1 0 0 0 1 0 0 1 1 1 1 1 1 0 1 $b $b diff --git a/tools/regression/file/dup/dup.c b/tools/regression/file/dup/dup.c index b0d9af2..8173818 100644 --- a/tools/regression/file/dup/dup.c +++ b/tools/regression/file/dup/dup.c @@ -29,6 +29,25 @@ * duped fd. * Test #17: check if fcntl(F_DUP2FD) to a fd > current maximum number of open * files limit work. + * Test #18: check if fcntl(F_DUPFD_CLOEXEC) works. + * Test #19: check if fcntl(F_DUPFD_CLOEXEC) set close-on-exec flag for duped + * fd. + * Test #20: check if fcntl(F_DUP2FD_CLOEXEC) works. + * Test #21: check if fcntl(F_DUP2FD_CLOEXEC) returned a fd we asked for. + * Test #22: check if fcntl(F_DUP2FD_CLOEXEC) set close-on-exec flag for duped + * fd. + * Test #23: check if fcntl(F_DUP2FD_CLOEXEC) to a fd > current maximum number + * of open files limit work. + * Test #24: check if dup3(O_CLOEXEC) works. + * Test #25: check if dup3(O_CLOEXEC) returned a fd we asked for. + * Test #26: check if dup3(O_CLOEXEC) set close-on-exec flag for duped fd. + * Test #27: check if dup3(0) works. + * Test #28: check if dup3(0) returned a fd we asked for. + * Test #29: check if dup3(0) cleared close-on-exec flag for duped fd. + * Test #30: check if dup3(O_CLOEXEC) fails if oldfd == newfd. + * Test #31: check if dup3(0) fails if oldfd == newfd. + * Test #32: check if dup3(O_CLOEXEC) to a fd > current maximum number of + * open files limit work. */ #include <sys/types.h> @@ -65,7 +84,7 @@ main(int __unused argc, char __unused *argv[]) orgfd = getafile(); - printf("1..17\n"); + printf("1..32\n"); /* If dup(2) ever work? */ if ((fd1 = dup(orgfd)) < 0) @@ -144,9 +163,13 @@ main(int __unused argc, char __unused *argv[]) printf("ok %d - dup2(2) didn't clear close-on-exec\n", test); /* Does fcntl(F_DUPFD) work? */ - if ((fd2 = fcntl(fd1, F_DUPFD)) < 0) + if ((fd2 = fcntl(fd1, F_DUPFD, 10)) < 0) err(1, "fcntl(F_DUPFD)"); - printf("ok %d - fcntl(F_DUPFD) works\n", ++test); + if (fd2 < 10) + printf("not ok %d - fcntl(F_DUPFD) returned wrong fd %d\n", + ++test, fd2); + else + printf("ok %d - fcntl(F_DUPFD) works\n", ++test); /* Was close-on-exec cleared? */ ++test; @@ -225,5 +248,139 @@ main(int __unused argc, char __unused *argv[]) printf("ok %d - fcntl(F_DUP2FD) didn't bypass NOFILE limit\n", test); + /* Does fcntl(F_DUPFD_CLOEXEC) work? */ + if ((fd2 = fcntl(fd1, F_DUPFD_CLOEXEC, 10)) < 0) + err(1, "fcntl(F_DUPFD_CLOEXEC)"); + if (fd2 < 10) + printf("not ok %d - fcntl(F_DUPFD_CLOEXEC) returned wrong fd %d\n", + ++test, fd2); + else + printf("ok %d - fcntl(F_DUPFD_CLOEXEC) works\n", ++test); + + /* Was close-on-exec cleared? */ + ++test; + if (fcntl(fd2, F_GETFD) != 1) + printf( + "not ok %d - fcntl(F_DUPFD_CLOEXEC) didn't set close-on-exec\n", + test); + else + printf("ok %d - fcntl(F_DUPFD_CLOEXEC) set close-on-exec\n", + test); + + /* If fcntl(F_DUP2FD_CLOEXEC) ever work? */ + if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, fd1 + 1)) < 0) + err(1, "fcntl(F_DUP2FD_CLOEXEC)"); + printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) works\n", ++test); + + /* Do we get the right fd? */ + ++test; + if (fd2 != fd1 + 1) + printf( + "no ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't give us the right fd\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) returned a correct fd\n", + test); + + /* Was close-on-exec set? */ + ++test; + if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) + printf( + "not ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't set close-on-exec\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) set close-on-exec\n", + test); + + /* + * It is unclear what F_DUP2FD_CLOEXEC should do when duplicating a + * file descriptor onto itself. + */ + + ++test; + if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) + err(1, "getrlimit"); + if ((fd2 = fcntl(fd1, F_DUP2FD_CLOEXEC, rlp.rlim_cur + 1)) >= 0) + printf("not ok %d - fcntl(F_DUP2FD_CLOEXEC) bypassed NOFILE limit\n", + test); + else + printf("ok %d - fcntl(F_DUP2FD_CLOEXEC) didn't bypass NOFILE limit\n", + test); + + /* Does dup3(O_CLOEXEC) ever work? */ + if ((fd2 = dup3(fd1, fd1 + 1, O_CLOEXEC)) < 0) + err(1, "dup3(O_CLOEXEC)"); + printf("ok %d - dup3(O_CLOEXEC) works\n", ++test); + + /* Do we get the right fd? */ + ++test; + if (fd2 != fd1 + 1) + printf( + "no ok %d - dup3(O_CLOEXEC) didn't give us the right fd\n", + test); + else + printf("ok %d - dup3(O_CLOEXEC) returned a correct fd\n", + test); + + /* Was close-on-exec set? */ + ++test; + if (fcntl(fd2, F_GETFD) != FD_CLOEXEC) + printf( + "not ok %d - dup3(O_CLOEXEC) didn't set close-on-exec\n", + test); + else + printf("ok %d - dup3(O_CLOEXEC) set close-on-exec\n", + test); + + /* Does dup3(0) ever work? */ + if ((fd2 = dup3(fd1, fd1 + 1, 0)) < 0) + err(1, "dup3(0)"); + printf("ok %d - dup3(0) works\n", ++test); + + /* Do we get the right fd? */ + ++test; + if (fd2 != fd1 + 1) + printf( + "no ok %d - dup3(0) didn't give us the right fd\n", + test); + else + printf("ok %d - dup3(0) returned a correct fd\n", + test); + + /* Was close-on-exec cleared? */ + ++test; + if (fcntl(fd2, F_GETFD) != 0) + printf( + "not ok %d - dup3(0) didn't clear close-on-exec\n", + test); + else + printf("ok %d - dup3(0) cleared close-on-exec\n", + test); + + /* dup3() does not allow duplicating to the same fd */ + ++test; + if (dup3(fd1, fd1, O_CLOEXEC) != -1) + printf( + "not ok %d - dup3(fd1, fd1, O_CLOEXEC) succeeded\n", test); + else + printf("ok %d - dup3(fd1, fd1, O_CLOEXEC) failed\n", test); + + ++test; + if (dup3(fd1, fd1, 0) != -1) + printf( + "not ok %d - dup3(fd1, fd1, 0) succeeded\n", test); + else + printf("ok %d - dup3(fd1, fd1, 0) failed\n", test); + + ++test; + if (getrlimit(RLIMIT_NOFILE, &rlp) < 0) + err(1, "getrlimit"); + if ((fd2 = dup3(fd1, rlp.rlim_cur + 1, O_CLOEXEC)) >= 0) + printf("not ok %d - dup3(O_CLOEXEC) bypassed NOFILE limit\n", + test); + else + printf("ok %d - dup3(O_CLOEXEC) didn't bypass NOFILE limit\n", + test); + return (0); } diff --git a/tools/regression/file/fcntlflags/Makefile b/tools/regression/file/fcntlflags/Makefile new file mode 100644 index 0000000..9e7fc3e --- /dev/null +++ b/tools/regression/file/fcntlflags/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= fcntlflags +MAN= +WARNS?= 6 + +.include <bsd.prog.mk> diff --git a/tools/regression/file/fcntlflags/fcntlflags.c b/tools/regression/file/fcntlflags/fcntlflags.c new file mode 100644 index 0000000..bcb3b54 --- /dev/null +++ b/tools/regression/file/fcntlflags/fcntlflags.c @@ -0,0 +1,110 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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$ + */ + +#include <sys/cdefs.h> + +#include <fcntl.h> +#include <stdio.h> +#include <unistd.h> + +/* + * O_ACCMODE is currently defined incorrectly. This is what it should be. + * Various code depends on the incorrect value. + */ +#define CORRECT_O_ACCMODE (O_ACCMODE | O_EXEC) + +static int testnum; + +static void +subtests(const char *path, int omode, const char *omodetext) +{ + int fd, flags1, flags2, flags3; + + fd = open(path, omode); + if (fd == -1) + printf("not ok %d - open(\"%s\", %s) failed\n", + testnum++, path, omodetext); + else + printf("ok %d - open(\"%s\", %s) succeeded\n", + testnum++, path, omodetext); + flags1 = fcntl(fd, F_GETFL); + if (flags1 == -1) + printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); + else if ((flags1 & CORRECT_O_ACCMODE) == omode) + printf("ok %d - fcntl(F_GETFL) gave correct result\n", + testnum++); + else + printf("not ok %d - fcntl(F_GETFL) gave incorrect result " + "(%#x & %#x != %#x)\n", + testnum++, flags1, CORRECT_O_ACCMODE, omode); + if (fcntl(fd, F_SETFL, flags1) == -1) + printf("not ok %d - fcntl(F_SETFL) same flags failed\n", + testnum++); + else + printf("ok %d - fcntl(F_SETFL) same flags succeeded\n", + testnum++); + flags2 = fcntl(fd, F_GETFL); + if (flags2 == -1) + printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); + else if (flags2 == flags1) + printf("ok %d - fcntl(F_GETFL) gave same result\n", + testnum++); + else + printf("not ok %d - fcntl(F_SETFL) caused fcntl(F_GETFL) to " + "change from %#x to %#x\n", + testnum++, flags1, flags2); + if (fcntl(fd, F_SETFL, flags2 | O_NONBLOCK) == -1) + printf("not ok %d - fcntl(F_SETFL) O_NONBLOCK failed\n", + testnum++); + else + printf("ok %d - fcntl(F_SETFL) O_NONBLOCK succeeded\n", + testnum++); + flags3 = fcntl(fd, F_GETFL); + if (flags3 == -1) + printf("not ok %d - fcntl(F_GETFL) failed\n", testnum++); + else if (flags3 == (flags2 | O_NONBLOCK)) + printf("ok %d - fcntl(F_GETFL) gave expected result\n", + testnum++); + else + printf("not ok %d - fcntl(F_SETFL) gave unexpected result " + "(%#x != %#x)\n", + testnum++, flags3, flags2 | O_NONBLOCK); + (void)close(fd); +} + +int +main(int argc __unused, char **argv __unused) +{ + printf("1..24\n"); + testnum = 1; + subtests("/dev/null", O_RDONLY, "O_RDONLY"); + subtests("/dev/null", O_WRONLY, "O_WRONLY"); + subtests("/dev/null", O_RDWR, "O_RDWR"); + subtests("/bin/sh", O_EXEC, "O_EXEC"); + return (0); +} diff --git a/tools/regression/file/fcntlflags/fcntlflags.t b/tools/regression/file/fcntlflags/fcntlflags.t new file mode 100644 index 0000000..8bdfd03 --- /dev/null +++ b/tools/regression/file/fcntlflags/fcntlflags.t @@ -0,0 +1,10 @@ +#!/bin/sh +# $FreeBSD$ + +cd `dirname $0` + +executable=`basename $0 .t` + +make $executable 2>&1 > /dev/null + +exec ./$executable diff --git a/tools/regression/filemon/Makefile b/tools/regression/filemon/Makefile index d92d20f..62a5296 100644 --- a/tools/regression/filemon/Makefile +++ b/tools/regression/filemon/Makefile @@ -1,10 +1,20 @@ # $FreeBSD$ -BINS= \ +.if ${MACHINE_ARCH} == "amd64" || ${MACHINE_ARCH} == "ia64" +BI_BITS= +.endif + +_BINS= \ filemontest \ - timed-forkb + timed-forkb \ + sizeof_long + +BINS= ${_BINS} +.if defined(BI_BITS) +BINS+= ${_BINS:C/$/32/g} +.endif -bins: filemontest timed-forkb +bins: ${BINS} all: bins NO_MAN= @@ -18,20 +28,25 @@ WITHOUT_CDDL= CLEANFILES+= ${BINS} -tests: bins + +.for f32 in ${BINS} +${f32}32: ${f32}.c + ${CC} -m32 -DBIT=\"32\" -o ${.TARGET} ${CFLAGS} ${.ALLSRC} +.endfor + +tests: kldstat | grep filemon - ${MAKE} test - @echo "Without filemon(4) active:" - ./timed-forkb - @echo "With filemon(4) active:" - script -f typescript-timed-forkb ./timed-forkb - ls -l typescript-timed-forkb.filemon + @echo "" + ${MAKE} test01 + ${MAKE} test02 +.if defined(BI_BITS) + ${MAKE} test32 +.endif @echo "filemon(4) tests passed." # Cannot use .OBJDIR -- 'filemontest' expects 'test_script.sh' in . -#FILEMONTEST32= filemontest32 -test: filemontest clean-test -.for BIN in filemontest ${FILEMONTEST32} +test01: ${BINS:Mfilemontest*} ${BINS:Msizeof_long*} clean-test +.for BIN in ${BINS:Mfilemontest} cd ${.CURDIR} ; \ for A in 1 2 3 4 5 6 7 8 9 0; do \ for B in 1 2 3 4 5 6 7 8 9 0; do \ @@ -41,13 +56,30 @@ test: filemontest clean-test done ;\ done @cd ${.CURDIR} ; set +e ; egrep '(Start|Stop) .*\.' filemon_log.* | \ - grep -q -v '\.[0-9][0-9][0-9][0-9][0-9][0-9]$$' || echo "Time stamp format OK" + grep -q -v '\.[0-9][0-9][0-9][0-9][0-9][0-9]$$' || printf "Time stamp format OK\n\n" .endfor + @cd ${.CURDIR} ; set +e ; for F in filemon_log.* ; do \ + tail -1 $$F | grep -q '# Bye bye' || echo "$$F missing filemon bye-bye" ; \ + NL=`wc -l $$F | awk '{print $$1}'` ; \ + if [ "$${NL}" != 97 ]; then echo "$$F BAD, contains $${NL} lines" ; exit 1 ; fi ; done + +test02: ${BINS:Mtimed-forkb*} + @echo "Without filemon(4) active:" + ./timed-forkb + @echo "With filemon(4) active:" + script -f typescript-timed-forkb ./timed-forkb + ls -l typescript-timed-forkb.filemon + +test32: ${BINS:M*32*} + script -f typescript.${.TARGET} ./sizeof_long32 >/dev/null + @tail -1 typescript.test32.filemon | grep -q '# Bye bye' || (echo '32-bit comapt filemon Missing "bye-bye"' ; exit 1) + @egrep -q '^X [0-9]+ 0$$' typescript.test32.filemon || (echo "32-bit binary exit ERROR" ; exit 1) + @printf "filemon(4) 32bit FreeBSD support passed.\n\n" CLEANFILES+= typescript-timed-forkb typescript-timed-forkb.filemon clean-test: - cd ${.CURDIR} ; rm -f filemon_log.* + cd ${.CURDIR} ; rm -f filemon_log*.* clean-tests: clean-test diff --git a/tools/regression/filemon/filemontest.c b/tools/regression/filemon/filemontest.c index 6f02547..03b53e2 100644 --- a/tools/regression/filemon/filemontest.c +++ b/tools/regression/filemon/filemontest.c @@ -43,9 +43,13 @@ __FBSDID("$FreeBSD$"); * "test_script.sh" in the cwd. */ +#ifndef BIT +#define BIT "" +#endif + int main(void) { - char log_name[] = "filemon_log.XXXXXX"; + char log_name[] = "filemon_log" BIT ".XXXXXX"; pid_t child; int fm_fd, fm_log; @@ -66,7 +70,7 @@ main(void) { child = getpid(); if (ioctl(fm_fd, FILEMON_SET_PID, &child) == -1) err(1, "Cannot set filemon PID to %d", child); - system("./test_script.sh"); + system("env BIT=" BIT " ./test_script.sh"); break; case -1: err(1, "Cannot fork"); diff --git a/tools/regression/filemon/test_script.sh b/tools/regression/filemon/test_script.sh index df34ec4..b69c238 100755 --- a/tools/regression/filemon/test_script.sh +++ b/tools/regression/filemon/test_script.sh @@ -41,3 +41,4 @@ ed -s $f1 < $f2 #w" | ed -s $f1 #rm $f1 $f2 uptime > /dev/null +sizeof_long${BIT} > /dev/null diff --git a/tools/regression/filemon/timed-forkb.c b/tools/regression/filemon/timed-forkb.c index a7df999..b7a0221 100644 --- a/tools/regression/filemon/timed-forkb.c +++ b/tools/regression/filemon/timed-forkb.c @@ -45,7 +45,7 @@ #define SLEEP 20 /* seconds */ #endif -int verbose; +static int verbose; static void usage(void) diff --git a/tools/regression/geom_uzip/.cvsignore b/tools/regression/geom_uzip/.cvsignore deleted file mode 100644 index 1e4f164..0000000 --- a/tools/regression/geom_uzip/.cvsignore +++ /dev/null @@ -1,2 +0,0 @@ -test-1.img -test-1.img.gz diff --git a/tools/regression/include/stdatomic/Makefile b/tools/regression/include/stdatomic/Makefile new file mode 100644 index 0000000..1ddd01a --- /dev/null +++ b/tools/regression/include/stdatomic/Makefile @@ -0,0 +1,7 @@ +# $FreeBSD$ + +PROG= logic +WARNS=6 +NO_MAN= + +.include <bsd.prog.mk> diff --git a/tools/regression/include/stdatomic/logic.c b/tools/regression/include/stdatomic/logic.c new file mode 100644 index 0000000..9659983 --- /dev/null +++ b/tools/regression/include/stdatomic/logic.c @@ -0,0 +1,128 @@ +/*- + * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> + * 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 <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <stdatomic.h> +#include <stdint.h> +#include <stdlib.h> +#include <string.h> + +/* + * Tool for testing the logical behaviour of operations on atomic + * integer types. These tests make no attempt to actually test whether + * the functions are atomic or provide the right barrier semantics. + * + * For every type, we create an array of 16 elements and repeat the test + * on every element in the array. This allows us to test whether the + * atomic operations have no effect on surrounding values. This is + * especially useful for the smaller integer types, as it may be the + * case that these operations are implemented by processing entire words + * (e.g. on MIPS). + */ + +static inline intmax_t +rndnum(void) +{ + intmax_t v; + + arc4random_buf(&v, sizeof(v)); + return (v); +} + +#define DO_FETCH_TEST(T, a, name, result) do { \ + T v1 = atomic_load(a); \ + T v2 = rndnum(); \ + assert(atomic_##name(a, v2) == v1); \ + assert(atomic_load(a) == (T)(result)); \ +} while (0) + +#define DO_COMPARE_EXCHANGE_TEST(T, a, name) do { \ + T v1 = atomic_load(a); \ + T v2 = rndnum(); \ + T v3 = rndnum(); \ + if (atomic_compare_exchange_##name(a, &v2, v3)) \ + assert(v1 == v2); \ + else \ + assert(atomic_compare_exchange_##name(a, &v2, v3)); \ + assert(atomic_load(a) == v3); \ +} while (0) + +#define DO_ALL_TESTS(T, a) do { \ + { \ + T v1 = rndnum(); \ + atomic_init(a, v1); \ + assert(atomic_load(a) == v1); \ + } \ + { \ + T v1 = rndnum(); \ + atomic_store(a, v1); \ + assert(atomic_load(a) == v1); \ + } \ + \ + DO_FETCH_TEST(T, a, exchange, v2); \ + DO_FETCH_TEST(T, a, fetch_add, v1 + v2); \ + DO_FETCH_TEST(T, a, fetch_and, v1 & v2); \ + DO_FETCH_TEST(T, a, fetch_or, v1 | v2); \ + DO_FETCH_TEST(T, a, fetch_sub, v1 - v2); \ + DO_FETCH_TEST(T, a, fetch_xor, v1 ^ v2); \ + \ + DO_COMPARE_EXCHANGE_TEST(T, a, weak); \ + DO_COMPARE_EXCHANGE_TEST(T, a, strong); \ +} while (0) + +#define TEST_TYPE(T) do { \ + int j; \ + struct { _Atomic(T) v[16]; } list, cmp; \ + arc4random_buf(&cmp, sizeof(cmp)); \ + for (j = 0; j < 16; j++) { \ + list = cmp; \ + DO_ALL_TESTS(T, &list.v[j]); \ + list.v[j] = cmp.v[j]; \ + assert(memcmp(&list, &cmp, sizeof(list)) == 0); \ + } \ +} while (0) + +int +main(void) +{ + int i; + + for (i = 0; i < 1000; i++) { + TEST_TYPE(int8_t); + TEST_TYPE(uint8_t); + TEST_TYPE(int16_t); + TEST_TYPE(uint16_t); + TEST_TYPE(int32_t); + TEST_TYPE(uint32_t); + TEST_TYPE(int64_t); + TEST_TYPE(uint64_t); + } + + return (0); +} diff --git a/tools/regression/lib/libc/gen/Makefile b/tools/regression/lib/libc/gen/Makefile index 4b29ad0..4cba5de 100644 --- a/tools/regression/lib/libc/gen/Makefile +++ b/tools/regression/lib/libc/gen/Makefile @@ -1,7 +1,7 @@ # $FreeBSD$ TESTS= test-arc4random test-fmtcheck test-fmtmsg test-fnmatch \ - test-fpclassify test-ftw test-posix_spawn test-wordexp + test-fpclassify test-ftw test-popen test-posix_spawn test-wordexp .PHONY: tests tests: ${TESTS} diff --git a/tools/regression/lib/libc/gen/test-fnmatch.c b/tools/regression/lib/libc/gen/test-fnmatch.c index 2544067..fd33574 100644 --- a/tools/regression/lib/libc/gen/test-fnmatch.c +++ b/tools/regression/lib/libc/gen/test-fnmatch.c @@ -135,6 +135,8 @@ struct testcase { "\\[", "\\[", 0, FNM_NOMATCH, "\\(", "\\(", 0, FNM_NOMATCH, "\\a", "\\a", 0, FNM_NOMATCH, + "\\", "\\", 0, FNM_NOMATCH, + "\\", "", 0, 0, "\\*", "\\*", FNM_NOESCAPE, 0, "\\?", "\\?", FNM_NOESCAPE, 0, "\\", "\\", FNM_NOESCAPE, 0, @@ -236,6 +238,8 @@ write_sh_tests(const char *progname, int num) if (strchr(t->pattern, '\'') != NULL || strchr(t->string, '\'') != NULL) continue; + if (t->flags == 0 && strcmp(t->pattern, "\\") == 0) + continue; if (num == 1 && t->flags == 0) printf("test%smatch '%s' '%s'\n", t->result == FNM_NOMATCH ? "no" : "", diff --git a/tools/regression/lib/libc/gen/test-fpclassify.c b/tools/regression/lib/libc/gen/test-fpclassify.c index 8431fe8..799c134 100644 --- a/tools/regression/lib/libc/gen/test-fpclassify.c +++ b/tools/regression/lib/libc/gen/test-fpclassify.c @@ -28,6 +28,7 @@ #include <assert.h> #include <math.h> +#include <stdio.h> #include <stdlib.h> int diff --git a/tools/regression/lib/libc/gen/test-ftw.c b/tools/regression/lib/libc/gen/test-ftw.c index adb0a17..209f033 100644 --- a/tools/regression/lib/libc/gen/test-ftw.c +++ b/tools/regression/lib/libc/gen/test-ftw.c @@ -34,6 +34,7 @@ __FBSDID("$FreeBSD$"); #include <sys/wait.h> #include <assert.h> +#include <err.h> #include <errno.h> #include <fcntl.h> #include <ftw.h> @@ -41,6 +42,7 @@ __FBSDID("$FreeBSD$"); #include <stdlib.h> #include <string.h> #include <spawn.h> +#include <unistd.h> extern char **environ; diff --git a/tools/regression/lib/libc/gen/test-popen.c b/tools/regression/lib/libc/gen/test-popen.c new file mode 100644 index 0000000..bf301d2 --- /dev/null +++ b/tools/regression/lib/libc/gen/test-popen.c @@ -0,0 +1,227 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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. + */ + +/* + * Limited test program for popen() as specified by IEEE Std. 1003.1-2008, + * with BSD extensions. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/wait.h> + +#include <assert.h> +#include <errno.h> +#include <fcntl.h> +#include <signal.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +static int failures; +static volatile sig_atomic_t got_sigpipe; + +static void +sigpipe_handler(int sig __unused) +{ + got_sigpipe = 1; +} + +static void +check_cloexec(FILE *fp, const char *mode) +{ + int flags; + + flags = fcntl(fileno(fp), F_GETFD); + if (flags == -1) + fprintf(stderr, "fcntl(F_GETFD) failed\n"), failures++; + else if ((flags & FD_CLOEXEC) != + (strchr(mode, 'e') != NULL ? FD_CLOEXEC : 0)) + fprintf(stderr, "Bad cloexec flag\n"), failures++; +} + +int +main(int argc, char *argv[]) +{ + FILE *fp, *fp2; + int i, j, status; + const char *mode; + const char *allmodes[] = { "r", "w", "r+", "re", "we", "r+e", "re+" }; + const char *rmodes[] = { "r", "r+", "re", "r+e", "re+" }; + const char *wmodes[] = { "w", "r+", "we", "r+e", "re+" }; + const char *rwmodes[] = { "r+", "r+e", "re+" }; + char buf[80]; + struct sigaction act, oact; + + for (i = 0; i < sizeof(allmodes) / sizeof(allmodes[0]); i++) { + mode = allmodes[i]; + fp = popen("exit 7", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 7) + fprintf(stderr, "Bad exit status (no I/O)\n"), failures++; + } + + for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { + mode = rmodes[i]; + fp = popen("exit 9", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + if (fgetc(fp) != EOF || !feof(fp) || ferror(fp)) + fprintf(stderr, "Input error 1\n"), failures++; + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 9) + fprintf(stderr, "Bad exit status (input)\n"), failures++; + } + + for (i = 0; i < sizeof(rmodes) / sizeof(rmodes[0]); i++) { + mode = rmodes[i]; + fp = popen("echo hi there", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + if (fgets(buf, sizeof(buf), fp) == NULL) + fprintf(stderr, "Input error 2\n"), failures++; + else if (strcmp(buf, "hi there\n") != 0) + fprintf(stderr, "Bad input 1\n"), failures++; + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + fprintf(stderr, "Bad exit status (input)\n"), failures++; + } + + for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { + mode = wmodes[i]; + fp = popen("read x && [ \"$x\" = abcd ]", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + if (fputs("abcd\n", fp) == EOF) + fprintf(stderr, "Output error 1\n"), failures++; + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + fprintf(stderr, "Bad exit status (output)\n"), failures++; + } + + act.sa_handler = sigpipe_handler; + act.sa_flags = SA_RESTART; + sigemptyset(&act.sa_mask); + if (sigaction(SIGPIPE, &act, &oact) == -1) + fprintf(stderr, "sigaction() failed\n"), failures++; + for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { + mode = wmodes[i]; + fp = popen("exit 88", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + got_sigpipe = 0; + while (fputs("abcd\n", fp) != EOF) + ; + if (!ferror(fp) || errno != EPIPE) + fprintf(stderr, "Expected EPIPE\n"), failures++; + if (!got_sigpipe) + fprintf(stderr, "Expected SIGPIPE\n"), failures++; + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 88) + fprintf(stderr, "Bad exit status (EPIPE)\n"), failures++; + } + if (sigaction(SIGPIPE, &oact, NULL) == -1) + fprintf(stderr, "sigaction() failed\n"), failures++; + + for (i = 0; i < sizeof(rwmodes) / sizeof(rwmodes[0]); i++) { + mode = rwmodes[i]; + fp = popen("read x && printf '%s\\n' \"Q${x#a}\"", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + check_cloexec(fp, mode); + if (fputs("abcd\n", fp) == EOF) + fprintf(stderr, "Output error 2\n"), failures++; + if (fgets(buf, sizeof(buf), fp) == NULL) + fprintf(stderr, "Input error 3\n"), failures++; + else if (strcmp(buf, "Qbcd\n") != 0) + fprintf(stderr, "Bad input 2\n"), failures++; + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 0) + fprintf(stderr, "Bad exit status (I/O)\n"), failures++; + } + + for (i = 0; i < sizeof(wmodes) / sizeof(wmodes[0]); i++) { + for (j = 0; j < sizeof(wmodes) / sizeof(wmodes[0]); j++) { + mode = wmodes[i]; + fp = popen("read x", mode); + if (fp == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + continue; + } + mode = wmodes[j]; + fp2 = popen("read x", mode); + if (fp2 == NULL) { + fprintf(stderr, "popen(, \"%s\") failed", mode); + failures++; + pclose(fp); + continue; + } + /* If fp2 inherits fp's pipe, we will deadlock here. */ + status = pclose(fp); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 1) { + fprintf(stderr, "Bad exit status (2 pipes)\n"); + failures++; + } + status = pclose(fp2); + if (!WIFEXITED(status) || WEXITSTATUS(status) != 1) { + fprintf(stderr, "Bad exit status (2 pipes)\n"); + failures++; + } + } + } + + if (failures == 0) + printf("PASS popen()\n"); + + return (failures != 0); +} diff --git a/tools/regression/lib/libc/gen/test-wordexp.c b/tools/regression/lib/libc/gen/test-wordexp.c index d94f870..15d1b7c 100644 --- a/tools/regression/lib/libc/gen/test-wordexp.c +++ b/tools/regression/lib/libc/gen/test-wordexp.c @@ -195,6 +195,18 @@ main(int argc, char *argv[]) r = wordexp("test } test", &we, 0); assert(r == WRDE_BADCHAR); + /* WRDE_SYNTAX */ + r = wordexp("'", &we, 0); + assert(r == WRDE_SYNTAX); + r = wordexp("'", &we, WRDE_UNDEF); + assert(r == WRDE_SYNTAX); + r = wordexp("'\\'", &we, 0); + assert(r == 0); + assert(we.we_wordc == 1); + assert(strcmp(we.we_wordv[0], "\\") == 0); + assert(we.we_wordv[1] == NULL); + wordfree(&we); + /* With a SIGCHLD handler that reaps all zombies. */ sa.sa_flags = 0; sigemptyset(&sa.sa_mask); diff --git a/tools/regression/lib/libc/locale/Makefile b/tools/regression/lib/libc/locale/Makefile index 5fb9a94..ebbd537 100644 --- a/tools/regression/lib/libc/locale/Makefile +++ b/tools/regression/lib/libc/locale/Makefile @@ -14,7 +14,9 @@ TESTS= test-mbrtowc \ test-wcstombs \ test-mblen \ test-iswctype \ - test-towctrans + test-towctrans \ + test-c16rtomb \ + test-mbrtoc16 .PHONY: tests tests: ${TESTS} diff --git a/tools/regression/lib/libc/locale/test-btowc.c b/tools/regression/lib/libc/locale/test-btowc.c index 9ed4582..b01c043 100644 --- a/tools/regression/lib/libc/locale/test-btowc.c +++ b/tools/regression/lib/libc/locale/test-btowc.c @@ -39,6 +39,7 @@ __FBSDID("$FreeBSD$"); #include <locale.h> #include <stdio.h> #include <stdlib.h> +#include <string.h> #include <wchar.h> int diff --git a/tools/regression/lib/libc/locale/test-c16rtomb.c b/tools/regression/lib/libc/locale/test-c16rtomb.c new file mode 100644 index 0000000..2c188fa --- /dev/null +++ b/tools/regression/lib/libc/locale/test-c16rtomb.c @@ -0,0 +1,145 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> + * 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. + */ +/* + * Test program for c16rtomb() as specified by ISO/IEC 9899:2011. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <uchar.h> + +int +main(int argc, char *argv[]) +{ + mbstate_t s; + char buf[MB_LEN_MAX + 1]; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* + * If the buffer argument is NULL, c16 is implicitly 0, + * c16rtomb() resets its internal state. + */ + assert(c16rtomb(NULL, L'\0', NULL) == 1); + assert(c16rtomb(NULL, 0xdc00, NULL) == 1); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0, &s) == 1); + assert((unsigned char)buf[0] == 0 && (unsigned char)buf[1] == 0xcc); + + /* Latin letter A, internal state. */ + assert(c16rtomb(NULL, L'\0', NULL) == 1); + assert(c16rtomb(NULL, L'A', NULL) == 1); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, L'A', &s) == 1); + assert((unsigned char)buf[0] == 'A' && (unsigned char)buf[1] == 0xcc); + + /* Unicode character 'Pile of poo'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0xd83d, &s) == 0); + assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1); + assert(errno == EILSEQ); + assert((unsigned char)buf[0] == 0xcc); + + /* + * ISO8859-1. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-1"), + "en_US.ISO8859-1") == 0); + + /* Unicode character 'Euro sign'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0x20ac, &s) == (size_t)-1); + assert(errno == EILSEQ); + assert((unsigned char)buf[0] == 0xcc); + + /* + * ISO8859-15. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-15"), + "en_US.ISO8859-15") == 0); + + /* Unicode character 'Euro sign'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0x20ac, &s) == 1); + assert((unsigned char)buf[0] == 0xa4 && (unsigned char)buf[1] == 0xcc); + + /* + * UTF-8. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.UTF-8"), "en_US.UTF-8") == 0); + + /* Unicode character 'Pile of poo'. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0xd83d, &s) == 0); + assert(c16rtomb(buf, 0xdca9, &s) == 4); + assert((unsigned char)buf[0] == 0xf0 && (unsigned char)buf[1] == 0x9f && + (unsigned char)buf[2] == 0x92 && (unsigned char)buf[3] == 0xa9 && + (unsigned char)buf[4] == 0xcc); + + /* Invalid code; 'Pile of poo' without the trail surrogate. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0xd83d, &s) == 0); + assert(c16rtomb(buf, L'A', &s) == (size_t)-1); + assert(errno == EILSEQ); + assert((unsigned char)buf[0] == 0xcc); + + /* Invalid code; 'Pile of poo' without the lead surrogate. */ + memset(&s, 0, sizeof(s)); + memset(buf, 0xcc, sizeof(buf)); + assert(c16rtomb(buf, 0xdca9, &s) == (size_t)-1); + assert(errno == EILSEQ); + assert((unsigned char)buf[0] == 0xcc); + + printf("ok 1 - c16rtomb()\n"); +} diff --git a/tools/regression/lib/libc/locale/test-iswctype.c b/tools/regression/lib/libc/locale/test-iswctype.c index ca9621a..1c56b88 100644 --- a/tools/regression/lib/libc/locale/test-iswctype.c +++ b/tools/regression/lib/libc/locale/test-iswctype.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <assert.h> #include <locale.h> #include <stdio.h> +#include <string.h> #include <wchar.h> #include <wctype.h> diff --git a/tools/regression/lib/libc/locale/test-mbrtoc16.c b/tools/regression/lib/libc/locale/test-mbrtoc16.c new file mode 100644 index 0000000..f709a9c --- /dev/null +++ b/tools/regression/lib/libc/locale/test-mbrtoc16.c @@ -0,0 +1,195 @@ +/*- + * Copyright (c) 2002 Tim J. Robbins + * All rights reserved. + * + * Copyright (c) 2013 Ed Schouten <ed@FreeBSD.org> + * 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. + */ +/* + * Test program for mbrtoc16() as specified by ISO/IEC 9899:2011. + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <errno.h> +#include <limits.h> +#include <locale.h> +#include <stdio.h> +#include <string.h> +#include <uchar.h> + +int +main(int argc, char *argv[]) +{ + mbstate_t s; + size_t len; + char16_t c16; + + /* + * C/POSIX locale. + */ + + printf("1..1\n"); + + /* Null wide character, internal state. */ + assert(mbrtoc16(&c16, "", 1, NULL) == 0); + assert(c16 == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "", 1, &s) == 0); + assert(c16 == 0); + + /* Latin letter A, internal state. */ + assert(mbrtoc16(NULL, 0, 0, NULL) == 0); + assert(mbrtoc16(&c16, "A", 1, NULL) == 1); + assert(c16 == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "A", 1, &s) == 1); + assert(c16 == L'A'); + + /* Incomplete character sequence. */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + assert(c16 == L'z'); + + /* Check that mbrtoc16() doesn't access the buffer when n == 0. */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + assert(c16 == L'z'); + + /* Check that mbrtoc16() doesn't read ahead too aggressively. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "AB", 2, &s) == 1); + assert(c16 == L'A'); + assert(mbrtoc16(&c16, "C", 1, &s) == 1); + assert(c16 == L'C'); + + /* + * ISO-8859-1. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-1"), + "en_US.ISO8859-1") == 0); + + /* Currency sign. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "\xa4", 1, &s) == 1); + assert(c16 == 0xa4); + + /* + * ISO-8859-15. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.ISO8859-15"), + "en_US.ISO8859-15") == 0); + + /* Euro sign. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "\xa4", 1, &s) == 1); + assert(c16 == 0x20ac); + + /* + * UTF-8. + */ + + assert(strcmp(setlocale(LC_CTYPE, "en_US.UTF-8"), "en_US.UTF-8") == 0); + + /* Null wide character, internal state. */ + assert(mbrtoc16(NULL, 0, 0, NULL) == 0); + assert(mbrtoc16(&c16, "", 1, NULL) == 0); + assert(c16 == 0); + + /* Null wide character. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "", 1, &s) == 0); + assert(c16 == 0); + + /* Latin letter A, internal state. */ + assert(mbrtoc16(NULL, 0, 0, NULL) == 0); + assert(mbrtoc16(&c16, "A", 1, NULL) == 1); + assert(c16 == L'A'); + + /* Latin letter A. */ + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "A", 1, &s) == 1); + assert(c16 == L'A'); + + /* Incomplete character sequence (zero length). */ + c16 = L'z'; + memset(&s, 0, sizeof(s)); + assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-2); + assert(c16 == L'z'); + + /* Incomplete character sequence (truncated double-byte). */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2); + + /* Same as above, but complete. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\xc3\x84", 2, &s) == 2); + assert(c16 == 0xc4); + + /* Test restarting behaviour. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\xc3", 1, &s) == (size_t)-2); + assert(c16 == 0); + assert(mbrtoc16(&c16, "\xb7", 1, &s) == 1); + assert(c16 == 0xf7); + + /* Surrogate pair. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\xf0\x9f\x92\xa9", 4, &s) == 4); + assert(c16 == 0xd83d); + assert(mbrtoc16(&c16, "", 0, &s) == (size_t)-3); + assert(c16 == 0xdca9); + + /* Letter e with acute, precomposed. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\xc3\xa9", 2, &s) == 2); + assert(c16 == 0xe9); + + /* Letter e with acute, combined. */ + memset(&s, 0, sizeof(s)); + c16 = 0; + assert(mbrtoc16(&c16, "\x65\xcc\x81", 3, &s) == 1); + assert(c16 == 0x65); + assert(mbrtoc16(&c16, "\xcc\x81", 2, &s) == 2); + assert(c16 == 0x301); + + printf("ok 1 - mbrtoc16()\n"); + + return (0); +} diff --git a/tools/regression/lib/libc/locale/test-towctrans.c b/tools/regression/lib/libc/locale/test-towctrans.c index 6c0e428..fabb343 100644 --- a/tools/regression/lib/libc/locale/test-towctrans.c +++ b/tools/regression/lib/libc/locale/test-towctrans.c @@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$"); #include <assert.h> #include <locale.h> #include <stdio.h> +#include <string.h> #include <wchar.h> #include <wctype.h> diff --git a/tools/regression/lib/libc/nss/test-getaddr.c b/tools/regression/lib/libc/nss/test-getaddr.c index 046d9db..309c94b 100644 --- a/tools/regression/lib/libc/nss/test-getaddr.c +++ b/tools/regression/lib/libc/nss/test-getaddr.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights rehted. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-getgr.c b/tools/regression/lib/libc/nss/test-getgr.c index 1b573e8..322c636 100644 --- a/tools/regression/lib/libc/nss/test-getgr.c +++ b/tools/regression/lib/libc/nss/test-getgr.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights regrped. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-gethostby.c b/tools/regression/lib/libc/nss/test-gethostby.c index 5a0c925..77455e7 100644 --- a/tools/regression/lib/libc/nss/test-gethostby.c +++ b/tools/regression/lib/libc/nss/test-gethostby.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights rehted. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-getproto.c b/tools/regression/lib/libc/nss/test-getproto.c index b94f204..89ad087 100644 --- a/tools/regression/lib/libc/nss/test-getproto.c +++ b/tools/regression/lib/libc/nss/test-getproto.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights repeed. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-getpw.c b/tools/regression/lib/libc/nss/test-getpw.c index 88277d3..bb88f6a 100644 --- a/tools/regression/lib/libc/nss/test-getpw.c +++ b/tools/regression/lib/libc/nss/test-getpw.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights repwded. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-getrpc.c b/tools/regression/lib/libc/nss/test-getrpc.c index df0bc83..4041e88 100644 --- a/tools/regression/lib/libc/nss/test-getrpc.c +++ b/tools/regression/lib/libc/nss/test-getrpc.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights repeed. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/test-getusershell.c b/tools/regression/lib/libc/nss/test-getusershell.c index 20faaac..8682591 100644 --- a/tools/regression/lib/libc/nss/test-getusershell.c +++ b/tools/regression/lib/libc/nss/test-getusershell.c @@ -1,6 +1,6 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights repwded. + * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/nss/testutil.h b/tools/regression/lib/libc/nss/testutil.h index f1e91c2..acd69ac 100644 --- a/tools/regression/lib/libc/nss/testutil.h +++ b/tools/regression/lib/libc/nss/testutil.h @@ -1,6 +1,5 @@ /*- * Copyright (c) 2006 Michael Bushkov <bushman@freebsd.org> - * All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions diff --git a/tools/regression/lib/libc/stdio/Makefile b/tools/regression/lib/libc/stdio/Makefile index f496f73..4b252b9 100644 --- a/tools/regression/lib/libc/stdio/Makefile +++ b/tools/regression/lib/libc/stdio/Makefile @@ -1,8 +1,8 @@ # $FreeBSD$ -TESTS= test-fmemopen test-getdelim test-open_memstream test-open_wmemstream \ - test-perror test-print-positional test-printbasic test-printfloat \ - test-scanfloat +TESTS= test-fmemopen test-getdelim test-mkostemp test-open_memstream \ + test-open_wmemstream test-perror test-print-positional test-printbasic \ + test-printfloat test-scanfloat CFLAGS+= -lm .PHONY: tests diff --git a/tools/regression/lib/libc/stdio/test-mkostemp.c b/tools/regression/lib/libc/stdio/test-mkostemp.c new file mode 100644 index 0000000..5f67c72 --- /dev/null +++ b/tools/regression/lib/libc/stdio/test-mkostemp.c @@ -0,0 +1,164 @@ +/*- + * Copyright (c) 2013 Jilles Tjoelker + * 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. + */ + +/* + * Test program for mkostemp(). + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/stat.h> + +#include <errno.h> +#include <fcntl.h> +#include <paths.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <unistd.h> + +static const char template[] = _PATH_TMP "mkostemp.XXXXXXXX"; +static int testnum; + +#define MISCFLAGS (O_APPEND | O_DIRECT | O_SHLOCK | O_EXLOCK | O_SYNC) + +static void +test_one(int oflags) +{ + char tmpf[sizeof(template)]; + struct stat st1, st2; + int fd; + + memcpy(tmpf, template, sizeof(tmpf)); + fd = mkostemp(tmpf, oflags); + if (fd < 0) { + printf("not ok %d - oflags=%#x " + "mkostemp() reported failure: %s\n", + testnum++, oflags, strerror(errno)); + return; + } + if (memcmp(tmpf, template, sizeof(tmpf) - 8 - 1) != 0) { + printf("not ok %d - oflags=%#x " + "returned pathname does not match template: %s\n", + testnum++, oflags, tmpf); + return; + } + do { + if (fcntl(fd, F_GETFD) != + (oflags & O_CLOEXEC ? FD_CLOEXEC : 0)) { + printf("not ok %d - oflags=%#x " + "close-on-exec flag incorrect\n", + testnum++, oflags); + break; + } + if ((fcntl(fd, F_GETFL) & MISCFLAGS) != (oflags & MISCFLAGS)) { + printf("not ok %d - oflags=%#x " + "open flags incorrect\n", + testnum++, oflags); + break; + } + if (stat(tmpf, &st1) == -1) { + printf("not ok %d - oflags=%#x " + "cannot stat returned pathname %s: %s\n", + testnum++, oflags, tmpf, strerror(errno)); + break; + } + if (fstat(fd, &st2) == -1) { + printf("not ok %d - oflags=%#x " + "cannot fstat returned fd %d: %s\n", + testnum++, oflags, fd, strerror(errno)); + break; + } + if (!S_ISREG(st1.st_mode) || (st1.st_mode & 0777) != 0600 || + st1.st_nlink != 1 || st1.st_size != 0) { + printf("not ok %d - oflags=%#x " + "named file attributes incorrect\n", + testnum++, oflags); + break; + } + if (!S_ISREG(st2.st_mode) || (st2.st_mode & 0777) != 0600 || + st2.st_nlink != 1 || st2.st_size != 0) { + printf("not ok %d - oflags=%#x " + "opened file attributes incorrect\n", + testnum++, oflags); + break; + } + if (st1.st_dev != st2.st_dev || st1.st_ino != st2.st_ino) { + printf("not ok %d - oflags=%#x " + "named and opened file do not match\n", + testnum++, oflags); + break; + } + (void)unlink(tmpf); + if (fstat(fd, &st2) == -1) + printf("not ok %d - oflags=%#x " + "cannot fstat returned fd %d again: %s\n", + testnum++, oflags, fd, strerror(errno)); + else if (st2.st_nlink != 0) + printf("not ok %d - oflags=%#x " + "st_nlink is not 0 after unlink\n", + testnum++, oflags); + else + printf("ok %d - oflags=%#x\n", testnum++, oflags); + (void)close(fd); + return; + } while (0); + (void)close(fd); + (void)unlink(tmpf); +} + +static void +test_badflags(void) +{ + char tmpf[sizeof(template)]; + + memcpy(tmpf, template, sizeof(tmpf)); + if (mkostemp(tmpf, O_CREAT) == -1) + printf("ok %d - mkostemp(O_CREAT) correctly failed\n", + testnum++); + else + printf("not ok %d - mkostemp(O_CREAT) wrongly succeeded\n", + testnum++); +} + +int +main(int argc, char *argv[]) +{ + int i; + const char *e; + + printf("1..5\n"); + testnum = 1; + + test_one(0); + test_one(O_CLOEXEC); + test_one(O_APPEND); + test_one(O_APPEND | O_CLOEXEC); + test_badflags(); + + return (0); +} diff --git a/tools/regression/lib/msun/Makefile b/tools/regression/lib/msun/Makefile index 261b1cb..dbf582f 100644 --- a/tools/regression/lib/msun/Makefile +++ b/tools/regression/lib/msun/Makefile @@ -2,9 +2,10 @@ TESTS= test-cexp test-conj test-csqrt test-ctrig \ test-exponential test-fenv test-fma \ - test-fmaxmin test-ilogb test-invtrig test-logarithm test-lrint \ + test-fmaxmin test-ilogb test-invtrig test-invctrig \ + test-logarithm test-lrint \ test-lround test-nan test-nearbyint test-next test-rem test-trig -CFLAGS+= -O0 -lm +CFLAGS+= -O0 -lm -Wno-unknown-pragmas .PHONY: tests tests: ${TESTS} diff --git a/tools/regression/lib/msun/test-cexp.c b/tools/regression/lib/msun/test-cexp.c index 2913fbd..78c3f1a 100644 --- a/tools/regression/lib/msun/test-cexp.c +++ b/tools/regression/lib/msun/test-cexp.c @@ -38,11 +38,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) -#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) -#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) -#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) +#include "test-utils.h" #define N(i) (sizeof(i) / sizeof((i)[0])) @@ -50,23 +46,6 @@ __FBSDID("$FreeBSD$"); #pragma STDC CX_LIMITED_RANGE OFF /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several @@ -83,14 +62,15 @@ cpackl(long double x, long double y) #define test(func, z, result, exceptmask, excepts, checksign) do { \ volatile long double complex _d = z; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(cfpequal((func)(_d), (result), (checksign))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test within a given tolerance. */ #define test_tol(func, z, result, tol) do { \ volatile long double complex _d = z; \ - assert(cfpequal_tol((func)(_d), (result), (tol))); \ + assert(cfpequal_tol((func)(_d), (result), (tol), \ + FPE_ABS_ZERO | CS_BOTH)); \ } while (0) /* Test all the functions that compute cexp(x). */ @@ -110,68 +90,7 @@ cpackl(long double x, long double y) /* Various finite non-zero numbers to test. */ static const float finites[] = -{ -42.0e20, -1.0 -1.0e-10, -0.0, 0.0, 1.0e-10, 1.0, 42.0e20 }; - -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - * If checksign is 0, we compare the absolute values instead. - */ -static int -fpequal(long double x, long double y, int checksign) -{ - if (isnan(x) || isnan(y)) - return (1); - if (checksign) - return (x == y && !signbit(x) == !signbit(y)); - else - return (fabsl(x) == fabsl(y)); -} - -static int -fpequal_tol(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y)) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - /* - * For our purposes here, if y=0, we interpret tol as an absolute - * tolerance. This is to account for roundoff in the input, e.g., - * cos(Pi/2) ~= 0. - */ - if (y == 0.0) - ret = fabsl(x - y) <= fabsl(tol); - else - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} - -static int -cfpequal(long double complex x, long double complex y, int checksign) -{ - return (fpequal(creal(x), creal(y), checksign) - && fpequal(cimag(x), cimag(y), checksign)); -} - -static int -cfpequal_tol(long double complex x, long double complex y, long double tol) -{ - return (fpequal_tol(creal(x), creal(y), tol) - && fpequal_tol(cimag(x), cimag(y), tol)); -} +{ -42.0e20, -1.0, -1.0e-10, -0.0, 0.0, 1.0e-10, 1.0, 42.0e20 }; /* Tests for 0 */ @@ -182,8 +101,8 @@ test_zero(void) /* cexp(0) = 1, no exceptions raised */ testall(0.0, 1.0, ALL_STD_EXCEPT, 0, 1); testall(-0.0, 1.0, ALL_STD_EXCEPT, 0, 1); - testall(cpackl(0.0, -0.0), cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(-0.0, -0.0), cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(-0.0, -0.0), CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, 1); } /* @@ -198,27 +117,27 @@ test_nan() /* cexp(x + NaNi) = NaN + NaNi and optionally raises invalid */ /* cexp(NaN + yi) = NaN + NaNi and optionally raises invalid (|y|>0) */ for (i = 0; i < N(finites); i++) { - testall(cpackl(finites[i], NAN), cpackl(NAN, NAN), + testall(CMPLXL(finites[i], NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~FE_INVALID, 0, 0); if (finites[i] == 0.0) continue; /* XXX FE_INEXACT shouldn't be raised here */ - testall(cpackl(NAN, finites[i]), cpackl(NAN, NAN), + testall(CMPLXL(NAN, finites[i]), CMPLXL(NAN, NAN), ALL_STD_EXCEPT & ~(FE_INVALID | FE_INEXACT), 0, 0); } /* cexp(NaN +- 0i) = NaN +- 0i */ - testall(cpackl(NAN, 0.0), cpackl(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(NAN, -0.0), cpackl(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(NAN, 0.0), CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(NAN, -0.0), CMPLXL(NAN, -0.0), ALL_STD_EXCEPT, 0, 1); /* cexp(inf + NaN i) = inf + nan i */ - testall(cpackl(INFINITY, NAN), cpackl(INFINITY, NAN), + testall(CMPLXL(INFINITY, NAN), CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); /* cexp(-inf + NaN i) = 0 */ - testall(cpackl(-INFINITY, NAN), cpackl(0.0, 0.0), + testall(CMPLXL(-INFINITY, NAN), CMPLXL(0.0, 0.0), ALL_STD_EXCEPT, 0, 0); /* cexp(NaN + NaN i) = NaN + NaN i */ - testall(cpackl(NAN, NAN), cpackl(NAN, NAN), + testall(CMPLXL(NAN, NAN), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, 0, 0); } @@ -228,24 +147,38 @@ test_inf(void) int i; /* cexp(x + inf i) = NaN + NaNi and raises invalid */ - /* cexp(inf + yi) = 0 + 0yi */ - /* cexp(-inf + yi) = inf + inf yi (except y=0) */ for (i = 0; i < N(finites); i++) { - testall(cpackl(finites[i], INFINITY), cpackl(NAN, NAN), + testall(CMPLXL(finites[i], INFINITY), CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 1); - /* XXX shouldn't raise an inexact exception */ - testall(cpackl(-INFINITY, finites[i]), - cpackl(0.0, 0.0 * finites[i]), - ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - if (finites[i] == 0) - continue; - testall(cpackl(INFINITY, finites[i]), - cpackl(INFINITY, INFINITY * finites[i]), - ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); } - testall(cpackl(INFINITY, 0.0), cpackl(INFINITY, 0.0), + /* cexp(-inf + yi) = 0 * (cos(y) + sin(y)i) */ + /* XXX shouldn't raise an inexact exception */ + testall(CMPLXL(-INFINITY, M_PI_4), CMPLXL(0.0, 0.0), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(-INFINITY, 3 * M_PI_4), CMPLXL(-0.0, 0.0), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(-INFINITY, 5 * M_PI_4), CMPLXL(-0.0, -0.0), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(-INFINITY, 7 * M_PI_4), CMPLXL(0.0, -0.0), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(-INFINITY, 0.0), CMPLXL(0.0, 0.0), + ALL_STD_EXCEPT, 0, 1); + testall(CMPLXL(-INFINITY, -0.0), CMPLXL(0.0, -0.0), + ALL_STD_EXCEPT, 0, 1); + /* cexp(inf + yi) = inf * (cos(y) + sin(y)i) (except y=0) */ + /* XXX shouldn't raise an inexact exception */ + testall(CMPLXL(INFINITY, M_PI_4), CMPLXL(INFINITY, INFINITY), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(INFINITY, 3 * M_PI_4), CMPLXL(-INFINITY, INFINITY), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(INFINITY, 5 * M_PI_4), CMPLXL(-INFINITY, -INFINITY), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + testall(CMPLXL(INFINITY, 7 * M_PI_4), CMPLXL(INFINITY, -INFINITY), + ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); + /* cexp(inf + 0i) = inf + 0i */ + testall(CMPLXL(INFINITY, 0.0), CMPLXL(INFINITY, 0.0), ALL_STD_EXCEPT, 0, 1); - testall(cpackl(INFINITY, -0.0), cpackl(INFINITY, -0.0), + testall(CMPLXL(INFINITY, -0.0), CMPLXL(INFINITY, -0.0), ALL_STD_EXCEPT, 0, 1); } @@ -256,17 +189,17 @@ test_reals(void) for (i = 0; i < N(finites); i++) { /* XXX could check exceptions more meticulously */ - test(cexp, cpackl(finites[i], 0.0), - cpackl(exp(finites[i]), 0.0), + test(cexp, CMPLXL(finites[i], 0.0), + CMPLXL(exp(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexp, cpackl(finites[i], -0.0), - cpackl(exp(finites[i]), -0.0), + test(cexp, CMPLXL(finites[i], -0.0), + CMPLXL(exp(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexpf, cpackl(finites[i], 0.0), - cpackl(expf(finites[i]), 0.0), + test(cexpf, CMPLXL(finites[i], 0.0), + CMPLXL(expf(finites[i]), 0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); - test(cexpf, cpackl(finites[i], -0.0), - cpackl(expf(finites[i]), -0.0), + test(cexpf, CMPLXL(finites[i], -0.0), + CMPLXL(expf(finites[i]), -0.0), FE_INVALID | FE_DIVBYZERO, 0, 1); } } @@ -277,17 +210,17 @@ test_imaginaries(void) int i; for (i = 0; i < N(finites); i++) { - test(cexp, cpackl(0.0, finites[i]), - cpackl(cos(finites[i]), sin(finites[i])), + test(cexp, CMPLXL(0.0, finites[i]), + CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexp, cpackl(-0.0, finites[i]), - cpackl(cos(finites[i]), sin(finites[i])), + test(cexp, CMPLXL(-0.0, finites[i]), + CMPLXL(cos(finites[i]), sin(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexpf, cpackl(0.0, finites[i]), - cpackl(cosf(finites[i]), sinf(finites[i])), + test(cexpf, CMPLXL(0.0, finites[i]), + CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); - test(cexpf, cpackl(-0.0, finites[i]), - cpackl(cosf(finites[i]), sinf(finites[i])), + test(cexpf, CMPLXL(-0.0, finites[i]), + CMPLXL(cosf(finites[i]), sinf(finites[i])), ALL_STD_EXCEPT & ~FE_INEXACT, 0, 1); } } @@ -312,12 +245,12 @@ test_small(void) b = tests[i + 1]; x = tests[i + 2]; y = tests[i + 3]; - test_tol(cexp, cpackl(a, b), cpackl(x, y), 3 * DBL_ULP()); + test_tol(cexp, CMPLXL(a, b), CMPLXL(x, y), 3 * DBL_ULP()); /* float doesn't have enough precision to pass these tests */ if (x == 0 || y == 0) continue; - test_tol(cexpf, cpackl(a, b), cpackl(x, y), 1 * FLT_ULP()); + test_tol(cexpf, CMPLXL(a, b), CMPLXL(x, y), 1 * FLT_ULP()); } } @@ -326,27 +259,27 @@ void test_large(void) { - test_tol(cexp, cpackl(709.79, 0x1p-1074), - cpackl(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); - test_tol(cexp, cpackl(1000, 0x1p-1074), - cpackl(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); - test_tol(cexp, cpackl(1400, 0x1p-1074), - cpackl(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); - test_tol(cexp, cpackl(900, 0x1.23456789abcdep-1020), - cpackl(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); - test_tol(cexp, cpackl(1300, 0x1.23456789abcdep-1020), - cpackl(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); - - test_tol(cexpf, cpackl(88.73, 0x1p-149), - cpackl(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(90, 0x1p-149), - cpackl(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(192, 0x1p-149), - cpackl(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(120, 0x1.234568p-120), - cpackl(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); - test_tol(cexpf, cpackl(170, 0x1.234568p-120), - cpackl(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); + test_tol(cexp, CMPLXL(709.79, 0x1p-1074), + CMPLXL(INFINITY, 8.94674309915433533273e-16), DBL_ULP()); + test_tol(cexp, CMPLXL(1000, 0x1p-1074), + CMPLXL(INFINITY, 9.73344457300016401328e+110), DBL_ULP()); + test_tol(cexp, CMPLXL(1400, 0x1p-1074), + CMPLXL(INFINITY, 5.08228858149196559681e+284), DBL_ULP()); + test_tol(cexp, CMPLXL(900, 0x1.23456789abcdep-1020), + CMPLXL(INFINITY, 7.42156649354218408074e+83), DBL_ULP()); + test_tol(cexp, CMPLXL(1300, 0x1.23456789abcdep-1020), + CMPLXL(INFINITY, 3.87514844965996756704e+257), DBL_ULP()); + + test_tol(cexpf, CMPLXL(88.73, 0x1p-149), + CMPLXL(INFINITY, 4.80265603e-07), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(90, 0x1p-149), + CMPLXL(INFINITY, 1.7101492622e-06f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(192, 0x1p-149), + CMPLXL(INFINITY, 3.396809344e+38f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(120, 0x1.234568p-120), + CMPLXL(INFINITY, 1.1163382522e+16f), 2 * FLT_ULP()); + test_tol(cexpf, CMPLXL(170, 0x1.234568p-120), + CMPLXL(INFINITY, 5.7878851079e+37f), 2 * FLT_ULP()); } int diff --git a/tools/regression/lib/msun/test-conj.c b/tools/regression/lib/msun/test-conj.c index 909e810..c261f60 100644 --- a/tools/regression/lib/msun/test-conj.c +++ b/tools/regression/lib/msun/test-conj.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> +#include "test-utils.h" + #pragma STDC CX_LIMITED_RANGE off /* Make sure gcc doesn't use builtin versions of these or honor __pure2. */ @@ -50,27 +52,6 @@ static float (*libcimagf)(float complex) = cimagf; static double (*libcimag)(double complex) = cimag; static long double (*libcimagl)(long double complex) = cimagl; -/* - * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. - * Fail an assertion if they differ. - */ -static int -fpequal(long double d1, long double d2) -{ - - if (d1 != d2) - return (isnan(d1) && isnan(d2)); - return (copysignl(1.0, d1) == copysignl(1.0, d2)); -} - -static int -cfpequal(long double complex d1, long double complex d2) -{ - - return (fpequal(creall(d1), creall(d2)) && - fpequal(cimagl(d1), cimagl(d2))); -} - static const double tests[] = { /* a + bI */ 0.0, 0.0, diff --git a/tools/regression/lib/msun/test-csqrt.c b/tools/regression/lib/msun/test-csqrt.c index 9877b9d..39176eb 100644 --- a/tools/regression/lib/msun/test-csqrt.c +++ b/tools/regression/lib/msun/test-csqrt.c @@ -37,6 +37,8 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> +#include "test-utils.h" + #define N(i) (sizeof(i) / sizeof((i)[0])) /* @@ -63,23 +65,6 @@ _csqrt(long double complex d) #pragma STDC CX_LIMITED_RANGE off /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. * Fail an assertion if they differ. */ @@ -87,20 +72,7 @@ static void assert_equal(long double complex d1, long double complex d2) { - if (isnan(creall(d1))) { - assert(isnan(creall(d2))); - } else { - assert(creall(d1) == creall(d2)); - assert(copysignl(1.0, creall(d1)) == - copysignl(1.0, creall(d2))); - } - if (isnan(cimagl(d1))) { - assert(isnan(cimagl(d2))); - } else { - assert(cimagl(d1) == cimagl(d2)); - assert(copysignl(1.0, cimagl(d1)) == - copysignl(1.0, cimagl(d2))); - } + assert(cfpequal(d1, d2)); } /* @@ -161,7 +133,7 @@ test_finite() b = tests[i + 1] * mults[j] * mults[j]; x = tests[i + 2] * mults[j]; y = tests[i + 3] * mults[j]; - assert(t_csqrt(cpackl(a, b)) == cpackl(x, y)); + assert(t_csqrt(CMPLXL(a, b)) == CMPLXL(x, y)); } } @@ -174,10 +146,10 @@ static void test_zeros() { - assert_equal(t_csqrt(cpackl(0.0, 0.0)), cpackl(0.0, 0.0)); - assert_equal(t_csqrt(cpackl(-0.0, 0.0)), cpackl(0.0, 0.0)); - assert_equal(t_csqrt(cpackl(0.0, -0.0)), cpackl(0.0, -0.0)); - assert_equal(t_csqrt(cpackl(-0.0, -0.0)), cpackl(0.0, -0.0)); + assert_equal(t_csqrt(CMPLXL(0.0, 0.0)), CMPLXL(0.0, 0.0)); + assert_equal(t_csqrt(CMPLXL(-0.0, 0.0)), CMPLXL(0.0, 0.0)); + assert_equal(t_csqrt(CMPLXL(0.0, -0.0)), CMPLXL(0.0, -0.0)); + assert_equal(t_csqrt(CMPLXL(-0.0, -0.0)), CMPLXL(0.0, -0.0)); } /* @@ -199,15 +171,15 @@ test_infinities() for (i = 0; i < N(vals); i++) { if (isfinite(vals[i])) { - assert_equal(t_csqrt(cpackl(-INFINITY, vals[i])), - cpackl(0.0, copysignl(INFINITY, vals[i]))); - assert_equal(t_csqrt(cpackl(INFINITY, vals[i])), - cpackl(INFINITY, copysignl(0.0, vals[i]))); + assert_equal(t_csqrt(CMPLXL(-INFINITY, vals[i])), + CMPLXL(0.0, copysignl(INFINITY, vals[i]))); + assert_equal(t_csqrt(CMPLXL(INFINITY, vals[i])), + CMPLXL(INFINITY, copysignl(0.0, vals[i]))); } - assert_equal(t_csqrt(cpackl(vals[i], INFINITY)), - cpackl(INFINITY, INFINITY)); - assert_equal(t_csqrt(cpackl(vals[i], -INFINITY)), - cpackl(INFINITY, -INFINITY)); + assert_equal(t_csqrt(CMPLXL(vals[i], INFINITY)), + CMPLXL(INFINITY, INFINITY)); + assert_equal(t_csqrt(CMPLXL(vals[i], -INFINITY)), + CMPLXL(INFINITY, -INFINITY)); } } @@ -218,26 +190,26 @@ static void test_nans() { - assert(creall(t_csqrt(cpackl(INFINITY, NAN))) == INFINITY); - assert(isnan(cimagl(t_csqrt(cpackl(INFINITY, NAN))))); - - assert(isnan(creall(t_csqrt(cpackl(-INFINITY, NAN))))); - assert(isinf(cimagl(t_csqrt(cpackl(-INFINITY, NAN))))); - - assert_equal(t_csqrt(cpackl(NAN, INFINITY)), - cpackl(INFINITY, INFINITY)); - assert_equal(t_csqrt(cpackl(NAN, -INFINITY)), - cpackl(INFINITY, -INFINITY)); - - assert_equal(t_csqrt(cpackl(0.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(-0.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(42.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(-42.0, NAN)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, 0.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, -0.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, 42.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, -42.0)), cpackl(NAN, NAN)); - assert_equal(t_csqrt(cpackl(NAN, NAN)), cpackl(NAN, NAN)); + assert(creall(t_csqrt(CMPLXL(INFINITY, NAN))) == INFINITY); + assert(isnan(cimagl(t_csqrt(CMPLXL(INFINITY, NAN))))); + + assert(isnan(creall(t_csqrt(CMPLXL(-INFINITY, NAN))))); + assert(isinf(cimagl(t_csqrt(CMPLXL(-INFINITY, NAN))))); + + assert_equal(t_csqrt(CMPLXL(NAN, INFINITY)), + CMPLXL(INFINITY, INFINITY)); + assert_equal(t_csqrt(CMPLXL(NAN, -INFINITY)), + CMPLXL(INFINITY, -INFINITY)); + + assert_equal(t_csqrt(CMPLXL(0.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(-0.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(42.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(-42.0, NAN)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, 0.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, -0.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, 42.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, -42.0)), CMPLXL(NAN, NAN)); + assert_equal(t_csqrt(CMPLXL(NAN, NAN)), CMPLXL(NAN, NAN)); } /* @@ -254,7 +226,7 @@ test_overflow(int maxexp) a = ldexpl(115 * 0x1p-8, maxexp); b = ldexpl(252 * 0x1p-8, maxexp); - result = t_csqrt(cpackl(a, b)); + result = t_csqrt(CMPLXL(a, b)); assert(creall(result) == ldexpl(14 * 0x1p-4, maxexp / 2)); assert(cimagl(result) == ldexpl(9 * 0x1p-4, maxexp / 2)); } diff --git a/tools/regression/lib/msun/test-ctrig.c b/tools/regression/lib/msun/test-ctrig.c index ed78661..9f9b88d 100644 --- a/tools/regression/lib/msun/test-ctrig.c +++ b/tools/regression/lib/msun/test-ctrig.c @@ -38,46 +38,12 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) -#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) -#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) -#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) -#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) -#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON #pragma STDC CX_LIMITED_RANGE OFF /* - * XXX gcc implements complex multiplication incorrectly. In - * particular, it implements it as if the CX_LIMITED_RANGE pragma - * were ON. Consequently, we need this function to form numbers - * such as x + INFINITY * I, since gcc evalutes INFINITY * I as - * NaN + INFINITY * I. - */ -static inline long double complex -cpackl(long double x, long double y) -{ - long double complex z; - - __real__ z = x; - __imag__ z = y; - return (z); -} - -/* Flags that determine whether to check the signs of the result. */ -#define CS_REAL 1 -#define CS_IMAG 2 -#define CS_BOTH (CS_REAL | CS_IMAG) - -#ifdef DEBUG -#define debug(...) printf(__VA_ARGS__) -#else -#define debug(...) (void)0 -#endif - -/* * Test that a function returns the correct value and sets the * exception flags correctly. The exceptmask specifies which * exceptions we should check. We need to be lenient for several @@ -95,8 +61,8 @@ cpackl(long double x, long double y) debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(cfpequal((func)(_d), (result), (checksign))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* @@ -108,7 +74,7 @@ cpackl(long double x, long double y) volatile long double complex _d = z; \ debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ creall(_d), cimagl(_d), creall(result), cimagl(result)); \ - assert(cfpequal_tol((func)(_d), (result), (tol))); \ + assert(cfpequal_tol((func)(_d), (result), (tol), FPE_ABS_ZERO)); \ } while (0) /* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ @@ -120,6 +86,14 @@ cpackl(long double x, long double y) test_p_tol(func, z, result, tol); \ test_p_tol(func, conjl(z), conjl(result), tol); \ } while (0) +#define test_odd_tol(func, z, result, tol) do { \ + test_tol(func, z, result, tol); \ + test_tol(func, -(z), -(result), tol); \ +} while (0) +#define test_even_tol(func, z, result, tol) do { \ + test_tol(func, z, result, tol); \ + test_tol(func, -(z), result, tol); \ +} while (0) /* Test the given function in all precisions. */ #define testall(func, x, result, exceptmask, excepts, checksign) do { \ @@ -144,87 +118,26 @@ cpackl(long double x, long double y) test_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) #define testall_odd_tol(func, x, result, tol) do { \ - test_tol(func, x, result, tol * DBL_ULP()); \ - test_tol(func, -x, -result, tol * DBL_ULP()); \ + test_odd_tol(func, x, result, tol * DBL_ULP()); \ + test_odd_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) #define testall_even_tol(func, x, result, tol) do { \ - test_tol(func, x, result, tol * DBL_ULP()); \ - test_tol(func, -x, result, tol * DBL_ULP()); \ + test_even_tol(func, x, result, tol * DBL_ULP()); \ + test_even_tol(func##f, x, result, tol * FLT_ULP()); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - * If checksign is 0, we compare the absolute values instead. - */ -static int -fpequal(long double x, long double y, int checksign) -{ - if (isnan(x) && isnan(y)) - return (1); - if (checksign) - return (x == y && !signbit(x) == !signbit(y)); - else - return (fabsl(x) == fabsl(y)); -} - -static int -fpequal_tol(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y) && tol == 0) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - /* - * For our purposes here, if y=0, we interpret tol as an absolute - * tolerance. This is to account for roundoff in the input, e.g., - * cos(Pi/2) ~= 0. - */ - if (y == 0.0) - ret = fabsl(x - y) <= fabsl(tol); - else - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} - -static int -cfpequal(long double complex x, long double complex y, int checksign) -{ - return (fpequal(creal(x), creal(y), checksign & CS_REAL) - && fpequal(cimag(x), cimag(y), checksign & CS_IMAG)); -} - -static int -cfpequal_tol(long double complex x, long double complex y, long double tol) -{ - return (fpequal_tol(creal(x), creal(y), tol) - && fpequal_tol(cimag(x), cimag(y), tol)); -} - /* Tests for 0 */ void test_zero(void) { - long double complex zero = cpackl(0.0, 0.0); + long double complex zero = CMPLXL(0.0, 0.0); /* csinh(0) = ctanh(0) = 0; ccosh(0) = 1 (no exceptions raised) */ testall_odd(csinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(csin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_even(ccosh, zero, 1.0, ALL_STD_EXCEPT, 0, CS_BOTH); - testall_even(ccos, zero, cpackl(1.0, -0.0), ALL_STD_EXCEPT, 0, CS_BOTH); + testall_even(ccos, zero, CMPLXL(1.0, -0.0), ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); testall_odd(ctan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); } @@ -235,7 +148,7 @@ test_zero(void) void test_nan() { - long double complex nan_nan = cpackl(NAN, NAN); + long double complex nan_nan = CMPLXL(NAN, NAN); long double complex z; /* @@ -256,7 +169,7 @@ test_nan() testall_even(ccos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); - z = cpackl(42, NAN); + z = CMPLXL(42, NAN); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); /* XXX We allow a spurious inexact exception here. */ @@ -265,7 +178,7 @@ test_nan() testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); - z = cpackl(NAN, 42); + z = CMPLXL(NAN, 42); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); @@ -274,38 +187,38 @@ test_nan() /* XXX We allow a spurious inexact exception here. */ testall_odd(ctan, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); - z = cpackl(NAN, INFINITY); + z = CMPLXL(NAN, INFINITY); testall_odd(csinh, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccosh, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); - testall_odd(csin, z, cpackl(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); - testall_even(ccos, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_odd(ctan, z, cpackl(0, 1), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_IMAG); - z = cpackl(INFINITY, NAN); - testall_odd(csinh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); - testall_even(ccosh, z, cpackl(INFINITY, NAN), ALL_STD_EXCEPT, 0, + z = CMPLXL(INFINITY, NAN); + testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); + testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - testall_odd(ctanh, z, cpackl(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); testall_odd(csin, z, nan_nan, OPT_INVALID, 0, 0); testall_even(ccos, z, nan_nan, OPT_INVALID, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); - z = cpackl(0, NAN); - testall_odd(csinh, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, 0); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); + z = CMPLXL(0, NAN); + testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, 0); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctanh, z, nan_nan, OPT_INVALID, 0, 0); - testall_odd(csin, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_odd(ctan, z, cpackl(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); - - z = cpackl(NAN, 0); - testall_odd(csinh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_odd(ctanh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); - testall_odd(csin, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(csin, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(ctan, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + + z = CMPLXL(NAN, 0); + testall_odd(csinh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_odd(ctanh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, 0); testall_odd(ctan, z, nan_nan, OPT_INVALID, 0, 0); } @@ -325,53 +238,53 @@ test_inf(void) * 0,Inf +-0,NaN inval NaN,+-0 inval NaN,NaN inval * finite,Inf NaN,NaN inval NaN,NaN inval NaN,NaN inval */ - z = cpackl(INFINITY, INFINITY); - testall_odd(csinh, z, cpackl(INFINITY, NAN), + z = CMPLXL(INFINITY, INFINITY); + testall_odd(csinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(INFINITY, NAN), + testall_even(ccosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctanh, z, cpackl(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); - testall_odd(csin, z, cpackl(NAN, INFINITY), + testall_odd(ctanh, z, CMPLXL(1, 0), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(csin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(INFINITY, NAN), + testall_even(ccos, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctan, z, cpackl(0, 1), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(ctan, z, CMPLXL(0, 1), ALL_STD_EXCEPT, 0, CS_REAL); /* XXX We allow spurious inexact exceptions here (hard to avoid). */ for (i = 0; i < sizeof(finites) / sizeof(finites[0]); i++) { - z = cpackl(INFINITY, finites[i]); + z = CMPLXL(INFINITY, finites[i]); c = INFINITY * cosl(finites[i]); s = finites[i] == 0 ? finites[i] : INFINITY * sinl(finites[i]); - testall_odd(csinh, z, cpackl(c, s), OPT_INEXACT, 0, CS_BOTH); - testall_even(ccosh, z, cpackl(c, s), OPT_INEXACT, 0, CS_BOTH); - testall_odd(ctanh, z, cpackl(1, 0 * sin(finites[i] * 2)), + testall_odd(csinh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); + testall_even(ccosh, z, CMPLXL(c, s), OPT_INEXACT, 0, CS_BOTH); + testall_odd(ctanh, z, CMPLXL(1, 0 * sin(finites[i] * 2)), OPT_INEXACT, 0, CS_BOTH); - z = cpackl(finites[i], INFINITY); - testall_odd(csin, z, cpackl(s, c), OPT_INEXACT, 0, CS_BOTH); - testall_even(ccos, z, cpackl(c, -s), OPT_INEXACT, 0, CS_BOTH); - testall_odd(ctan, z, cpackl(0 * sin(finites[i] * 2), 1), + z = CMPLXL(finites[i], INFINITY); + testall_odd(csin, z, CMPLXL(s, c), OPT_INEXACT, 0, CS_BOTH); + testall_even(ccos, z, CMPLXL(c, -s), OPT_INEXACT, 0, CS_BOTH); + testall_odd(ctan, z, CMPLXL(0 * sin(finites[i] * 2), 1), OPT_INEXACT, 0, CS_BOTH); } - z = cpackl(0, INFINITY); - testall_odd(csinh, z, cpackl(0, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctanh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - z = cpackl(INFINITY, 0); - testall_odd(csin, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_odd(ctan, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - - z = cpackl(42, INFINITY); - testall_odd(csinh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccosh, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + z = CMPLXL(0, INFINITY); + testall_odd(csinh, z, CMPLXL(0, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccosh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctanh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + z = CMPLXL(INFINITY, 0); + testall_odd(csin, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccos, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctan, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + + z = CMPLXL(42, INFINITY); + testall_odd(csinh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccosh, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ - testall_odd(ctanh, z, cpackl(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); - z = cpackl(INFINITY, 42); - testall_odd(csin, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); - testall_even(ccos, z, cpackl(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_odd(ctanh, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); + z = CMPLXL(INFINITY, 42); + testall_odd(csin, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); + testall_even(ccos, z, CMPLXL(NAN, NAN), ALL_STD_EXCEPT, FE_INVALID, 0); /* XXX We allow a spurious inexact exception here. */ - testall_odd(ctan, z, cpackl(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); + testall_odd(ctan, z, CMPLXL(NAN, NAN), OPT_INEXACT, FE_INVALID, 0); } /* Tests along the real and imaginary axes. */ @@ -387,26 +300,50 @@ test_axes(void) for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { /* Real axis */ - z = cpackl(nums[i], 0.0); - testall_odd_tol(csinh, z, cpackl(sinh(nums[i]), 0), 0); - testall_even_tol(ccosh, z, cpackl(cosh(nums[i]), 0), 0); - testall_odd_tol(ctanh, z, cpackl(tanh(nums[i]), 0), 1); - testall_odd_tol(csin, z, cpackl(sin(nums[i]), - copysign(0, cos(nums[i]))), 0); - testall_even_tol(ccos, z, cpackl(cos(nums[i]), - -copysign(0, sin(nums[i]))), 0); - testall_odd_tol(ctan, z, cpackl(tan(nums[i]), 0), 1); + z = CMPLXL(nums[i], 0.0); + test_odd_tol(csinh, z, CMPLXL(sinh(nums[i]), 0), DBL_ULP()); + test_even_tol(ccosh, z, CMPLXL(cosh(nums[i]), 0), DBL_ULP()); + test_odd_tol(ctanh, z, CMPLXL(tanh(nums[i]), 0), DBL_ULP()); + test_odd_tol(csin, z, CMPLXL(sin(nums[i]), + copysign(0, cos(nums[i]))), DBL_ULP()); + test_even_tol(ccos, z, CMPLXL(cos(nums[i]), + -copysign(0, sin(nums[i]))), DBL_ULP()); + test_odd_tol(ctan, z, CMPLXL(tan(nums[i]), 0), DBL_ULP()); + + test_odd_tol(csinhf, z, CMPLXL(sinhf(nums[i]), 0), FLT_ULP()); + test_even_tol(ccoshf, z, CMPLXL(coshf(nums[i]), 0), FLT_ULP()); + printf("%a %a\n", creal(z), cimag(z)); + printf("%a %a\n", creal(ctanhf(z)), cimag(ctanhf(z))); + printf("%a\n", nextafterf(tanhf(nums[i]), INFINITY)); + test_odd_tol(ctanhf, z, CMPLXL(tanhf(nums[i]), 0), + 1.3 * FLT_ULP()); + test_odd_tol(csinf, z, CMPLXL(sinf(nums[i]), + copysign(0, cosf(nums[i]))), FLT_ULP()); + test_even_tol(ccosf, z, CMPLXL(cosf(nums[i]), + -copysign(0, sinf(nums[i]))), 2 * FLT_ULP()); + test_odd_tol(ctanf, z, CMPLXL(tanf(nums[i]), 0), FLT_ULP()); /* Imaginary axis */ - z = cpackl(0.0, nums[i]); - testall_odd_tol(csinh, z, cpackl(copysign(0, cos(nums[i])), - sin(nums[i])), 0); - testall_even_tol(ccosh, z, cpackl(cos(nums[i]), - copysign(0, sin(nums[i]))), 0); - testall_odd_tol(ctanh, z, cpackl(0, tan(nums[i])), 1); - testall_odd_tol(csin, z, cpackl(0, sinh(nums[i])), 0); - testall_even_tol(ccos, z, cpackl(cosh(nums[i]), -0.0), 0); - testall_odd_tol(ctan, z, cpackl(0, tanh(nums[i])), 1); + z = CMPLXL(0.0, nums[i]); + test_odd_tol(csinh, z, CMPLXL(copysign(0, cos(nums[i])), + sin(nums[i])), DBL_ULP()); + test_even_tol(ccosh, z, CMPLXL(cos(nums[i]), + copysign(0, sin(nums[i]))), DBL_ULP()); + test_odd_tol(ctanh, z, CMPLXL(0, tan(nums[i])), DBL_ULP()); + test_odd_tol(csin, z, CMPLXL(0, sinh(nums[i])), DBL_ULP()); + test_even_tol(ccos, z, CMPLXL(cosh(nums[i]), -0.0), DBL_ULP()); + test_odd_tol(ctan, z, CMPLXL(0, tanh(nums[i])), DBL_ULP()); + + test_odd_tol(csinhf, z, CMPLXL(copysign(0, cosf(nums[i])), + sinf(nums[i])), FLT_ULP()); + test_even_tol(ccoshf, z, CMPLXL(cosf(nums[i]), + copysign(0, sinf(nums[i]))), FLT_ULP()); + test_odd_tol(ctanhf, z, CMPLXL(0, tanf(nums[i])), FLT_ULP()); + test_odd_tol(csinf, z, CMPLXL(0, sinhf(nums[i])), FLT_ULP()); + test_even_tol(ccosf, z, CMPLXL(coshf(nums[i]), -0.0), + FLT_ULP()); + test_odd_tol(ctanf, z, CMPLXL(0, tanhf(nums[i])), + 1.3 * FLT_ULP()); } } @@ -462,13 +399,13 @@ test_small(void) int i; for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { - z = cpackl(tests[i].a, tests[i].b); + z = CMPLXL(tests[i].a, tests[i].b); testall_odd_tol(csinh, z, - cpackl(tests[i].sinh_a, tests[i].sinh_b), 1.1); + CMPLXL(tests[i].sinh_a, tests[i].sinh_b), 1.1); testall_even_tol(ccosh, z, - cpackl(tests[i].cosh_a, tests[i].cosh_b), 1.1); + CMPLXL(tests[i].cosh_a, tests[i].cosh_b), 1.1); testall_odd_tol(ctanh, z, - cpackl(tests[i].tanh_a, tests[i].tanh_b), 1.1); + CMPLXL(tests[i].tanh_a, tests[i].tanh_b), 1.4); } } @@ -479,36 +416,39 @@ test_large(void) long double complex z; /* tanh() uses a threshold around x=22, so check both sides. */ - z = cpackl(21, 0.78539816339744830961566084581987572L); + z = CMPLXL(21, 0.78539816339744830961566084581987572L); testall_odd_tol(ctanh, z, - cpackl(1.0, 1.14990445285871196133287617611468468e-18L), 1); + CMPLXL(1.0, 1.14990445285871196133287617611468468e-18L), 1.2); z++; testall_odd_tol(ctanh, z, - cpackl(1.0, 1.55622644822675930314266334585597964e-19L), 1); - - z = cpackl(355, 0.78539816339744830961566084581987572L); - testall_odd_tol(ctanh, z, - cpackl(1.0, 8.95257245135025991216632140458264468e-309L), 1); - z = cpackl(30, 0x1p1023L); - testall_odd_tol(ctanh, z, - cpackl(1.0, -1.62994325413993477997492170229268382e-26L), 1); - z = cpackl(1, 0x1p1023L); - testall_odd_tol(ctanh, z, - cpackl(0.878606311888306869546254022621986509L, - -0.225462792499754505792678258169527424L), 1); - - z = cpackl(710.6, 0.78539816339744830961566084581987572L); - testall_odd_tol(csinh, z, - cpackl(1.43917579766621073533185387499658944e308L, - 1.43917579766621073533185387499658944e308L), 1); - testall_even_tol(ccosh, z, - cpackl(1.43917579766621073533185387499658944e308L, - 1.43917579766621073533185387499658944e308L), 1); - - z = cpackl(1500, 0.78539816339744830961566084581987572L); - testall_odd(csinh, z, cpackl(INFINITY, INFINITY), OPT_INEXACT, + CMPLXL(1.0, 1.55622644822675930314266334585597964e-19L), 1); + + z = CMPLXL(355, 0.78539816339744830961566084581987572L); + test_odd_tol(ctanh, z, + CMPLXL(1.0, 8.95257245135025991216632140458264468e-309L), + DBL_ULP()); + z = CMPLXL(30, 0x1p1023L); + test_odd_tol(ctanh, z, + CMPLXL(1.0, -1.62994325413993477997492170229268382e-26L), + DBL_ULP()); + z = CMPLXL(1, 0x1p1023L); + test_odd_tol(ctanh, z, + CMPLXL(0.878606311888306869546254022621986509L, + -0.225462792499754505792678258169527424L), + DBL_ULP()); + + z = CMPLXL(710.6, 0.78539816339744830961566084581987572L); + test_odd_tol(csinh, z, + CMPLXL(1.43917579766621073533185387499658944e308L, + 1.43917579766621073533185387499658944e308L), DBL_ULP()); + test_even_tol(ccosh, z, + CMPLXL(1.43917579766621073533185387499658944e308L, + 1.43917579766621073533185387499658944e308L), DBL_ULP()); + + z = CMPLXL(1500, 0.78539816339744830961566084581987572L); + testall_odd(csinh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); - testall_even(ccosh, z, cpackl(INFINITY, INFINITY), OPT_INEXACT, + testall_even(ccosh, z, CMPLXL(INFINITY, INFINITY), OPT_INEXACT, FE_OVERFLOW, CS_BOTH); } diff --git a/tools/regression/lib/msun/test-exponential.c b/tools/regression/lib/msun/test-exponential.c index 53a6116..010e0fd 100644 --- a/tools/regression/lib/msun/test-exponential.c +++ b/tools/regression/lib/msun/test-exponential.c @@ -41,8 +41,7 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -63,7 +62,7 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) /* Test all the functions that compute b^x. */ @@ -81,17 +80,6 @@ __FBSDID("$FreeBSD$"); test(expm1f, x, result, exceptmask, excepts); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - void run_generic_tests(void) { diff --git a/tools/regression/lib/msun/test-fma.c b/tools/regression/lib/msun/test-fma.c index 1237a60..1fcf889 100644 --- a/tools/regression/lib/msun/test-fma.c +++ b/tools/regression/lib/msun/test-fma.c @@ -37,8 +37,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -53,14 +52,17 @@ __FBSDID("$FreeBSD$"); * meaningful error messages. */ #define test(func, x, y, z, result, exceptmask, excepts) do { \ + volatile long double _vx = (x), _vy = (y), _vz = (z); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal((func)((x), (y), (z)), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(fpequal((func)(_vx, _vy, _vz), (result))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(x, y, z, result, exceptmask, excepts) do { \ - test(fma, (x), (y), (z), (double)(result), (exceptmask), (excepts)); \ - test(fmaf, (x), (y), (z), (float)(result), (exceptmask), (excepts)); \ + test(fma, (double)(x), (double)(y), (double)(z), \ + (double)(result), (exceptmask), (excepts)); \ + test(fmaf, (float)(x), (float)(y), (float)(z), \ + (float)(result), (exceptmask), (excepts)); \ test(fmal, (x), (y), (z), (result), (exceptmask), (excepts)); \ } while (0) @@ -77,17 +79,10 @@ __FBSDID("$FreeBSD$"); } while (0) /* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN + * This is needed because clang constant-folds fma in ways that are incorrect + * in rounding modes other than FE_TONEAREST. */ -int -fpequal(long double x, long double y) -{ - - return ((x == y && !signbit(x) == !signbit(y)) - || (isnan(x) && isnan(y))); -} +volatile double one = 1.0; static void test_zeroes(void) @@ -108,9 +103,9 @@ test_zeroes(void) testall(-0.0, 0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); testall(0.0, -0.0, -0.0, -0.0, ALL_STD_EXCEPT, 0); - testall(-1.0, 1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); - testall(1.0, -1.0, 1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); - testall(-1.0, -1.0, -1.0, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); + testall(-one, one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); + testall(one, -one, one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); + testall(-one, -one, -one, rd ? -0.0 : 0.0, ALL_STD_EXCEPT, 0); switch (fegetround()) { case FE_TONEAREST: @@ -190,53 +185,53 @@ test_small_z(void) /* x*y positive, z positive */ if (fegetround() == FE_UPWARD) { - test(fmaf, 1.0, 1.0, 0x1.0p-100, 1.0 + FLT_EPSILON, + test(fmaf, one, one, 0x1.0p-100, 1.0 + FLT_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); - test(fma, 1.0, 1.0, 0x1.0p-200, 1.0 + DBL_EPSILON, + test(fma, one, one, 0x1.0p-200, 1.0 + DBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); - test(fmal, 1.0, 1.0, 0x1.0p-200, 1.0 + LDBL_EPSILON, + test(fmal, one, one, 0x1.0p-200, 1.0 + LDBL_EPSILON, ALL_STD_EXCEPT, FE_INEXACT); } else { - testall(0x1.0p100, 1.0, 0x1.0p-100, 0x1.0p100, + testall(0x1.0p100, one, 0x1.0p-100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y negative, z negative */ if (fegetround() == FE_DOWNWARD) { - test(fmaf, -1.0, 1.0, -0x1.0p-100, -(1.0 + FLT_EPSILON), + test(fmaf, -one, one, -0x1.0p-100, -(1.0 + FLT_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); - test(fma, -1.0, 1.0, -0x1.0p-200, -(1.0 + DBL_EPSILON), + test(fma, -one, one, -0x1.0p-200, -(1.0 + DBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); - test(fmal, -1.0, 1.0, -0x1.0p-200, -(1.0 + LDBL_EPSILON), + test(fmal, -one, one, -0x1.0p-200, -(1.0 + LDBL_EPSILON), ALL_STD_EXCEPT, FE_INEXACT); } else { - testall(0x1.0p100, -1.0, -0x1.0p-100, -0x1.0p100, + testall(0x1.0p100, -one, -0x1.0p-100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y positive, z negative */ if (fegetround() == FE_DOWNWARD || fegetround() == FE_TOWARDZERO) { - test(fmaf, 1.0, 1.0, -0x1.0p-100, 1.0 - FLT_EPSILON / 2, + test(fmaf, one, one, -0x1.0p-100, 1.0 - FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); - test(fma, 1.0, 1.0, -0x1.0p-200, 1.0 - DBL_EPSILON / 2, + test(fma, one, one, -0x1.0p-200, 1.0 - DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); - test(fmal, 1.0, 1.0, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2, + test(fmal, one, one, -0x1.0p-200, 1.0 - LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { - testall(0x1.0p100, 1.0, -0x1.0p-100, 0x1.0p100, + testall(0x1.0p100, one, -0x1.0p-100, 0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } /* x*y negative, z positive */ if (fegetround() == FE_UPWARD || fegetround() == FE_TOWARDZERO) { - test(fmaf, -1.0, 1.0, 0x1.0p-100, -1.0 + FLT_EPSILON / 2, + test(fmaf, -one, one, 0x1.0p-100, -1.0 + FLT_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); - test(fma, -1.0, 1.0, 0x1.0p-200, -1.0 + DBL_EPSILON / 2, + test(fma, -one, one, 0x1.0p-200, -1.0 + DBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); - test(fmal, -1.0, 1.0, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2, + test(fmal, -one, one, 0x1.0p-200, -1.0 + LDBL_EPSILON / 2, ALL_STD_EXCEPT, FE_INEXACT); } else { - testall(-0x1.0p100, 1.0, 0x1.0p-100, -0x1.0p100, + testall(-0x1.0p100, one, 0x1.0p-100, -0x1.0p100, ALL_STD_EXCEPT, FE_INEXACT); } } diff --git a/tools/regression/lib/msun/test-fmaxmin.c b/tools/regression/lib/msun/test-fmaxmin.c index fdba529..7ddcc87 100644 --- a/tools/regression/lib/msun/test-fmaxmin.c +++ b/tools/regression/lib/msun/test-fmaxmin.c @@ -36,25 +36,11 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON /* - * Test for equality with two special rules: - * fpequal(NaN, NaN) is true - * fpequal(+0.0, -0.0) is false - */ -static inline int -fpequal(long double x, long double y) -{ - - return ((x == y && !signbit(x) == !signbit(y)) - || (isnan(x) && isnan(y))); -} - -/* * Test whether func(x, y) has the expected result, and make sure no * exceptions are raised. */ diff --git a/tools/regression/lib/msun/test-invctrig.c b/tools/regression/lib/msun/test-invctrig.c new file mode 100644 index 0000000..e78c26b --- /dev/null +++ b/tools/regression/lib/msun/test-invctrig.c @@ -0,0 +1,372 @@ +/*- + * Copyright (c) 2008-2013 David Schultz <das@FreeBSD.org> + * 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. + */ + +/* + * Tests for casin[h](), cacos[h](), and catan[h](). + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <assert.h> +#include <complex.h> +#include <fenv.h> +#include <float.h> +#include <math.h> +#include <stdio.h> + +#include "test-utils.h" + +#pragma STDC FENV_ACCESS ON +#pragma STDC CX_LIMITED_RANGE OFF + +/* + * Test that a function returns the correct value and sets the + * exception flags correctly. The exceptmask specifies which + * exceptions we should check. We need to be lenient for several + * reasons, but mainly because on some architectures it's impossible + * to raise FE_OVERFLOW without raising FE_INEXACT. + * + * These are macros instead of functions so that assert provides more + * meaningful error messages. + * + * XXX The volatile here is to avoid gcc's bogus constant folding and work + * around the lack of support for the FENV_ACCESS pragma. + */ +#define test_p(func, z, result, exceptmask, excepts, checksign) do { \ + volatile long double complex _d = z; \ + debug(" testing %s(%Lg + %Lg I) == %Lg + %Lg I\n", #func, \ + creall(_d), cimagl(_d), creall(result), cimagl(result)); \ + assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ + assert(cfpequal_cs((func)(_d), (result), (checksign))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ +} while (0) + +/* + * Test within a given tolerance. The tolerance indicates relative error + * in ulps. + */ +#define test_p_tol(func, z, result, tol) do { \ + volatile long double complex _d = z; \ + debug(" testing %s(%Lg + %Lg I) ~= %Lg + %Lg I\n", #func, \ + creall(_d), cimagl(_d), creall(result), cimagl(result)); \ + assert(cfpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ +} while (0) + +/* These wrappers apply the identities f(conj(z)) = conj(f(z)). */ +#define test(func, z, result, exceptmask, excepts, checksign) do { \ + test_p(func, z, result, exceptmask, excepts, checksign); \ + test_p(func, conjl(z), conjl(result), exceptmask, excepts, checksign); \ +} while (0) +#define test_tol(func, z, result, tol) do { \ + test_p_tol(func, z, result, tol); \ + test_p_tol(func, conjl(z), conjl(result), tol); \ +} while (0) + +/* Test the given function in all precisions. */ +#define testall(func, x, result, exceptmask, excepts, checksign) do { \ + test(func, x, result, exceptmask, excepts, checksign); \ + test(func##f, x, result, exceptmask, excepts, checksign); \ +} while (0) +#define testall_odd(func, x, result, exceptmask, excepts, checksign) do { \ + testall(func, x, result, exceptmask, excepts, checksign); \ + testall(func, -(x), -result, exceptmask, excepts, checksign); \ +} while (0) +#define testall_even(func, x, result, exceptmask, excepts, checksign) do { \ + testall(func, x, result, exceptmask, excepts, checksign); \ + testall(func, -(x), result, exceptmask, excepts, checksign); \ +} while (0) + +/* + * Test the given function in all precisions, within a given tolerance. + * The tolerance is specified in ulps. + */ +#define testall_tol(func, x, result, tol) do { \ + test_tol(func, x, result, (tol) * DBL_ULP()); \ + test_tol(func##f, x, result, (tol) * FLT_ULP()); \ +} while (0) +#define testall_odd_tol(func, x, result, tol) do { \ + testall_tol(func, x, result, tol); \ + testall_tol(func, -(x), -result, tol); \ +} while (0) +#define testall_even_tol(func, x, result, tol) do { \ + testall_tol(func, x, result, tol); \ + testall_tol(func, -(x), result, tol); \ +} while (0) + +static const long double +pi = 3.14159265358979323846264338327950280L, +c3pi = 9.42477796076937971538793014983850839L; + + +/* Tests for 0 */ +void +test_zero(void) +{ + long double complex zero = CMPLXL(0.0, 0.0); + + testall_tol(cacosh, zero, CMPLXL(0.0, pi / 2), 1); + testall_tol(cacosh, -zero, CMPLXL(0.0, -pi / 2), 1); + testall_tol(cacos, zero, CMPLXL(pi / 2, -0.0), 1); + testall_tol(cacos, -zero, CMPLXL(pi / 2, 0.0), 1); + + testall_odd(casinh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + testall_odd(casin, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + + testall_odd(catanh, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); + testall_odd(catan, zero, zero, ALL_STD_EXCEPT, 0, CS_BOTH); +} + +/* + * Tests for NaN inputs. + */ +void +test_nan() +{ + long double complex nan_nan = CMPLXL(NAN, NAN); + long double complex z; + + /* + * IN CACOSH CACOS CASINH CATANH + * NaN,NaN NaN,NaN NaN,NaN NaN,NaN NaN,NaN + * finite,NaN NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* + * NaN,finite NaN,NaN* NaN,NaN* NaN,NaN* NaN,NaN* + * NaN,Inf Inf,NaN NaN,-Inf ?Inf,NaN ?0,pi/2 + * +-Inf,NaN Inf,NaN NaN,?Inf +-Inf,NaN +-0,NaN + * +-0,NaN NaN,NaN* pi/2,NaN NaN,NaN* +-0,NaN + * NaN,0 NaN,NaN* NaN,NaN* NaN,0 NaN,NaN* + * + * * = raise invalid + */ + z = nan_nan; + testall(cacosh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(cacos, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(casinh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(casin, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(catanh, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + testall(catan, z, nan_nan, ALL_STD_EXCEPT, 0, 0); + + z = CMPLXL(0.5, NAN); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); + testall(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = CMPLXL(NAN, 0.5); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, 0); + testall(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = CMPLXL(NAN, INFINITY); + testall(cacosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall(cacosh, -z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall(cacos, z, CMPLXL(NAN, -INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); + testall(casinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, 0); + testall(casin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, CS_IMAG); + testall_tol(catanh, z, CMPLXL(0.0, pi / 2), 1); + testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, CS_IMAG); + + z = CMPLXL(INFINITY, NAN); + testall_even(cacosh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, + CS_REAL); + testall_even(cacos, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_odd(casinh, z, CMPLXL(INFINITY, NAN), ALL_STD_EXCEPT, 0, + CS_REAL); + testall_odd(casin, z, CMPLXL(NAN, INFINITY), ALL_STD_EXCEPT, 0, 0); + testall_odd(catanh, z, CMPLXL(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd_tol(catan, z, CMPLXL(pi / 2, 0.0), 1); + + z = CMPLXL(0.0, NAN); + /* XXX We allow a spurious inexact exception here. */ + testall_even(cacosh, z, nan_nan, OPT_INVALID & ~FE_INEXACT, 0, 0); + testall_even_tol(cacos, z, CMPLXL(pi / 2, NAN), 1); + testall_odd(casinh, z, nan_nan, OPT_INVALID, 0, 0); + testall_odd(casin, z, CMPLXL(0.0, NAN), ALL_STD_EXCEPT, 0, CS_REAL); + testall_odd(catanh, z, CMPLXL(0.0, NAN), OPT_INVALID, 0, CS_REAL); + testall_odd(catan, z, nan_nan, OPT_INVALID, 0, 0); + + z = CMPLXL(NAN, 0.0); + testall(cacosh, z, nan_nan, OPT_INVALID, 0, 0); + testall(cacos, z, nan_nan, OPT_INVALID, 0, 0); + testall(casinh, z, CMPLXL(NAN, 0), ALL_STD_EXCEPT, 0, CS_IMAG); + testall(casin, z, nan_nan, OPT_INVALID, 0, 0); + testall(catanh, z, nan_nan, OPT_INVALID, 0, CS_IMAG); + testall(catan, z, CMPLXL(NAN, 0.0), ALL_STD_EXCEPT, 0, 0); +} + +void +test_inf(void) +{ + long double complex z; + + /* + * IN CACOSH CACOS CASINH CATANH + * Inf,Inf Inf,pi/4 pi/4,-Inf Inf,pi/4 0,pi/2 + * -Inf,Inf Inf,3pi/4 3pi/4,-Inf --- --- + * Inf,finite Inf,0 0,-Inf Inf,0 0,pi/2 + * -Inf,finite Inf,pi pi,-Inf --- --- + * finite,Inf Inf,pi/2 pi/2,-Inf Inf,pi/2 0,pi/2 + */ + z = CMPLXL(INFINITY, INFINITY); + testall_tol(cacosh, z, CMPLXL(INFINITY, pi / 4), 1); + testall_tol(cacosh, -z, CMPLXL(INFINITY, -c3pi / 4), 1); + testall_tol(cacos, z, CMPLXL(pi / 4, -INFINITY), 1); + testall_tol(cacos, -z, CMPLXL(c3pi / 4, INFINITY), 1); + testall_odd_tol(casinh, z, CMPLXL(INFINITY, pi / 4), 1); + testall_odd_tol(casin, z, CMPLXL(pi / 4, INFINITY), 1); + testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); + testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); + + z = CMPLXL(INFINITY, 0.5); + /* XXX We allow a spurious inexact exception here. */ + testall(cacosh, z, CMPLXL(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); + testall_tol(cacosh, -z, CMPLXL(INFINITY, -pi), 1); + testall(cacos, z, CMPLXL(0, -INFINITY), OPT_INEXACT, 0, CS_BOTH); + testall_tol(cacos, -z, CMPLXL(pi, INFINITY), 1); + testall_odd(casinh, z, CMPLXL(INFINITY, 0), OPT_INEXACT, 0, CS_BOTH); + testall_odd_tol(casin, z, CMPLXL(pi / 2, INFINITY), 1); + testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); + testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); + + z = CMPLXL(0.5, INFINITY); + testall_tol(cacosh, z, CMPLXL(INFINITY, pi / 2), 1); + testall_tol(cacosh, -z, CMPLXL(INFINITY, -pi / 2), 1); + testall_tol(cacos, z, CMPLXL(pi / 2, -INFINITY), 1); + testall_tol(cacos, -z, CMPLXL(pi / 2, INFINITY), 1); + testall_odd_tol(casinh, z, CMPLXL(INFINITY, pi / 2), 1); + /* XXX We allow a spurious inexact exception here. */ + testall_odd(casin, z, CMPLXL(0.0, INFINITY), OPT_INEXACT, 0, CS_BOTH); + testall_odd_tol(catanh, z, CMPLXL(0, pi / 2), 1); + testall_odd_tol(catan, z, CMPLXL(pi / 2, 0), 1); +} + +/* Tests along the real and imaginary axes. */ +void +test_axes(void) +{ + static const long double nums[] = { + -2, -1, -0.5, 0.5, 1, 2 + }; + long double complex z; + int i; + + for (i = 0; i < sizeof(nums) / sizeof(nums[0]); i++) { + /* Real axis */ + z = CMPLXL(nums[i], 0.0); + if (fabs(nums[i]) <= 1) { + testall_tol(cacosh, z, CMPLXL(0.0, acos(nums[i])), 1); + testall_tol(cacos, z, CMPLXL(acosl(nums[i]), -0.0), 1); + testall_tol(casin, z, CMPLXL(asinl(nums[i]), 0.0), 1); + testall_tol(catanh, z, CMPLXL(atanh(nums[i]), 0.0), 1); + } else { + testall_tol(cacosh, z, + CMPLXL(acosh(fabs(nums[i])), + (nums[i] < 0) ? pi : 0), 1); + testall_tol(cacos, z, + CMPLXL((nums[i] < 0) ? pi : 0, + -acosh(fabs(nums[i]))), 1); + testall_tol(casin, z, + CMPLXL(copysign(pi / 2, nums[i]), + acosh(fabs(nums[i]))), 1); + testall_tol(catanh, z, + CMPLXL(atanh(1 / nums[i]), pi / 2), 1); + } + testall_tol(casinh, z, CMPLXL(asinh(nums[i]), 0.0), 1); + testall_tol(catan, z, CMPLXL(atan(nums[i]), 0), 1); + + /* TODO: Test the imaginary axis. */ + } +} + +void +test_small(void) +{ + /* + * z = 0.75 + i 0.25 + * acos(z) = Pi/4 - i ln(2)/2 + * asin(z) = Pi/4 + i ln(2)/2 + * atan(z) = atan(4)/2 + i ln(17/9)/4 + */ + static const struct { + complex long double z; + complex long double acos_z; + complex long double asin_z; + complex long double atan_z; + } tests[] = { + { CMPLXL(0.75L, 0.25L), + CMPLXL(pi / 4, -0.34657359027997265470861606072908828L), + CMPLXL(pi / 4, 0.34657359027997265470861606072908828L), + CMPLXL(0.66290883183401623252961960521423782L, + 0.15899719167999917436476103600701878L) }, + }; + int i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + testall_tol(cacos, tests[i].z, tests[i].acos_z, 2); + testall_odd_tol(casin, tests[i].z, tests[i].asin_z, 2); + testall_odd_tol(catan, tests[i].z, tests[i].atan_z, 2); + } +} + +/* Test inputs that might cause overflow in a sloppy implementation. */ +void +test_large(void) +{ + + /* TODO: Write these tests */ +} + +int +main(int argc, char *argv[]) +{ + + printf("1..6\n"); + + test_zero(); + printf("ok 1 - invctrig zero\n"); + + test_nan(); + printf("ok 2 - invctrig nan\n"); + + test_inf(); + printf("ok 3 - invctrig inf\n"); + + test_axes(); + printf("ok 4 - invctrig axes\n"); + + test_small(); + printf("ok 5 - invctrig small\n"); + + test_large(); + printf("ok 6 - invctrig large\n"); + + return (0); +} diff --git a/tools/regression/lib/msun/test-invtrig.c b/tools/regression/lib/msun/test-invtrig.c index 05d310f..2523d59 100644 --- a/tools/regression/lib/msun/test-invtrig.c +++ b/tools/regression/lib/msun/test-invtrig.c @@ -39,8 +39,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #define LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -58,8 +57,8 @@ __FBSDID("$FreeBSD$"); #define test_tol(func, x, result, tol, excepts) do { \ volatile long double _in = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal(func(_in), _out, (tol))); \ - assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ + assert(fpequal_tol(func(_in), _out, (tol), CS_BOTH)); \ + assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test(func, x, result, excepts) \ test_tol(func, (x), (result), 0, (excepts)) @@ -78,8 +77,8 @@ __FBSDID("$FreeBSD$"); #define test2_tol(func, y, x, result, tol, excepts) do { \ volatile long double _iny = (y), _inx = (x), _out = (result); \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ - assert(fpequal(func(_iny, _inx), _out, (tol))); \ - assert((func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ + assert(fpequal_tol(func(_iny, _inx), _out, (tol), CS_BOTH)); \ + assert(((void)func, fetestexcept(ALL_STD_EXCEPT) == (excepts))); \ } while (0) #define test2(func, y, x, result, excepts) \ test2_tol(func, (y), (x), (result), 0, (excepts)) @@ -104,33 +103,6 @@ c7pi = 2.19911485751285526692385036829565196e+01L, c5pio3 = 5.23598775598298873077107230546583851e+00L, sqrt2m1 = 4.14213562373095048801688724209698081e-01L; -/* - * Determine whether x and y are equal to within a relative error of tol, - * with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y, long double tol) -{ - fenv_t env; - int ret; - - if (isnan(x) && isnan(y)) - return (1); - if (!signbit(x) != !signbit(y)) - return (0); - if (x == y) - return (1); - if (tol == 0) - return (0); - - /* Hard case: need to check the tolerance. */ - feholdexcept(&env); - ret = fabsl(x - y) <= fabsl(y * tol); - fesetenv(&env); - return (ret); -} /* * Test special case inputs in asin(), acos() and atan(): signed diff --git a/tools/regression/lib/msun/test-logarithm.c b/tools/regression/lib/msun/test-logarithm.c index 258c514..18b9ebe 100644 --- a/tools/regression/lib/msun/test-logarithm.c +++ b/tools/regression/lib/msun/test-logarithm.c @@ -41,8 +41,7 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #pragma STDC FENV_ACCESS ON @@ -63,36 +62,42 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ +} while (0) + +#define test(func, x, result, exceptmask, excepts) do { \ + volatile long double _d = x; \ + assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ + assert(fpequal((func)(_d), (result))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ +} while (0) + +#define test_tol(func, z, result, tol) do { \ + volatile long double _d = z; \ + debug(" testing %6s(%15La) ~= % .36Le\n", #func, _d, result); \ + assert(fpequal_tol((func)(_d), (result), (tol), CS_BOTH)); \ } while (0) /* Test all the functions that compute log(x). */ #define testall0(x, result, exceptmask, excepts) do { \ test(log, x, result, exceptmask, excepts); \ test(logf, x, result, exceptmask, excepts); \ + test(logl, x, result, exceptmask, excepts); \ test(log2, x, result, exceptmask, excepts); \ test(log2f, x, result, exceptmask, excepts); \ + test(log2l, x, result, exceptmask, excepts); \ test(log10, x, result, exceptmask, excepts); \ test(log10f, x, result, exceptmask, excepts); \ + test(log10l, x, result, exceptmask, excepts); \ } while (0) /* Test all the functions that compute log(1+x). */ #define testall1(x, result, exceptmask, excepts) do { \ test(log1p, x, result, exceptmask, excepts); \ test(log1pf, x, result, exceptmask, excepts); \ + test(log1pl, x, result, exceptmask, excepts); \ } while (0) -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - void run_generic_tests(void) { @@ -140,6 +145,13 @@ run_log2_tests(void) assert(log2(ldexp(1.0, i)) == i); assert(fetestexcept(ALL_STD_EXCEPT) == 0); } + for (i = LDBL_MIN_EXP - LDBL_MANT_DIG; i < LDBL_MAX_EXP; i++) { + assert(log2l(ldexpl(1.0, i)) == i); +#if 0 + /* XXX This test does not pass yet. */ + assert(fetestexcept(ALL_STD_EXCEPT) == 0); +#endif + } } void @@ -151,7 +163,17 @@ run_roundingmode_tests(void) */ fesetround(FE_DOWNWARD); /* These are still positive per IEEE 754R */ +#if 0 testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); +#else + /* logl, log2l, and log10l don't pass yet. */ + test(log, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(logf, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log2, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log2f, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log10, 1.0, 0.0, ALL_STD_EXCEPT, 0); + test(log10f, 1.0, 0.0, ALL_STD_EXCEPT, 0); +#endif testall1(0.0, 0.0, ALL_STD_EXCEPT, 0); fesetround(FE_TOWARDZERO); testall0(1.0, 0.0, ALL_STD_EXCEPT, 0); @@ -166,11 +188,84 @@ run_roundingmode_tests(void) fesetround(FE_TONEAREST); } +void +run_accuracy_tests(void) +{ + static const struct { + float x; + long double log2x; + long double logex; + long double log10x; + } tests[] = { + { 0x1p-120 + 0x1p-140, + -1.19999998624139449158861798943319717e2L, + -8.31776607135195754708796206665656732e1L, + -3.61235990655024477716980559136055915e1L, + }, + { 1.0 - 0x1p-20, + -1.37586186296463416424364914705656460e-6L, + -9.53674771153890007250243736279163253e-7L, + -4.14175690642480911859354110516159131e-7L, }, + { 1.0 + 0x1p-20, + 1.37586055084113820105668028340371476e-6L, + 9.53673861659188233908415514963336144e-7L, + 4.14175295653950611453333571759200697e-7L }, + { 19.75, + 4.30378074817710292442728634194115348e0L, + 2.98315349134713087533848129856505779e0L, + 1.29556709996247903756734359702926363e0L }, + { 19.75 * 0x1p100, + 1.043037807481771029244272863419411534e2L, + 7.229787154734166181706169344438271459e1L, + 3.139856666636059855894123306947856631e1L }, + }; + int i; + + for (i = 0; i < sizeof(tests) / sizeof(tests[0]); i++) { + test_tol(log2, tests[i].x, tests[i].log2x, DBL_ULP()); + test_tol(log2f, tests[i].x, tests[i].log2x, FLT_ULP()); + test_tol(log2l, tests[i].x, tests[i].log2x, LDBL_ULP()); + test_tol(log, tests[i].x, tests[i].logex, DBL_ULP()); + test_tol(logf, tests[i].x, tests[i].logex, FLT_ULP()); + test_tol(logl, tests[i].x, tests[i].logex, LDBL_ULP()); + test_tol(log10, tests[i].x, tests[i].log10x, DBL_ULP()); + test_tol(log10f, tests[i].x, tests[i].log10x, FLT_ULP()); + test_tol(log10l, tests[i].x, tests[i].log10x, LDBL_ULP()); + if (tests[i].x >= 0.5) { + test_tol(log1p, tests[i].x - 1, tests[i].logex, + DBL_ULP()); + test_tol(log1pf, tests[i].x - 1, tests[i].logex, + FLT_ULP()); + test_tol(log1pl, tests[i].x - 1, tests[i].logex, + LDBL_ULP()); + } + } +} + +void +run_log1p_accuracy_tests(void) +{ + + test_tol(log1pf, 0x0.333333p0F, + 1.82321546859847114303367992804596800640e-1L, FLT_ULP()); + test_tol(log1p, 0x0.3333333333333p0, + 1.82321556793954589204283870982629267635e-1L, DBL_ULP()); + test_tol(log1pl, 0x0.33333333333333332p0L, + 1.82321556793954626202683007050468762914e-1L, LDBL_ULP()); + + test_tol(log1pf, -0x0.333333p0F, + -2.23143536413048672940940199918017467652e-1L, FLT_ULP()); + test_tol(log1p, -0x0.3333333333333p0, + -2.23143551314209700255143859052009022937e-1L, DBL_ULP()); + test_tol(log1pl, -0x0.33333333333333332p0L, + -2.23143551314209755752742563153765697950e-1L, LDBL_ULP()); +} + int main(int argc, char *argv[]) { - printf("1..3\n"); + printf("1..5\n"); run_generic_tests(); printf("ok 1 - logarithm\n"); @@ -181,5 +276,11 @@ main(int argc, char *argv[]) run_roundingmode_tests(); printf("ok 3 - logarithm\n"); + run_accuracy_tests(); + printf("ok 4 - logarithm\n"); + + run_log1p_accuracy_tests(); + printf("ok 5 - logarithm\n"); + return (0); } diff --git a/tools/regression/lib/msun/test-nearbyint.c b/tools/regression/lib/msun/test-nearbyint.c index 7251acb..602ea2a 100644 --- a/tools/regression/lib/msun/test-nearbyint.c +++ b/tools/regression/lib/msun/test-nearbyint.c @@ -40,8 +40,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" static int testnum; @@ -49,6 +48,14 @@ static const int rmodes[] = { FE_TONEAREST, FE_DOWNWARD, FE_UPWARD, FE_TOWARDZERO, }; +/* Make sure we're testing the library, not some broken compiler built-ins. */ +double (*libnearbyint)(double) = nearbyint; +float (*libnearbyintf)(float) = nearbyintf; +long double (*libnearbyintl)(long double) = nearbyintl; +#define nearbyintf libnearbyintf +#define nearbyint libnearbyint +#define nearbyintl libnearbyintl + static const struct { float in; float out[3]; /* one answer per rounding mode except towardzero */ @@ -64,19 +71,6 @@ static const struct { static const int ntests = sizeof(tests) / sizeof(tests[0]); -/* - * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. - * Fail an assertion if they differ. - */ -static int -fpequal(long double d1, long double d2) -{ - - if (d1 != d2) - return (isnan(d1) && isnan(d2)); - return (copysignl(1.0, d1) == copysignl(1.0, d2)); -} - /* Get the appropriate result for the current rounding mode. */ static float get_output(int testindex, int rmodeindex, int negative) @@ -107,7 +101,7 @@ test_nearby(int testindex) in = tests[testindex].in; out = get_output(testindex, i, 0); - assert(fpequal(out, nearbyintf(in))); + assert(fpequal(out, libnearbyintf(in))); assert(fpequal(out, nearbyint(in))); assert(fpequal(out, nearbyintl(in))); assert(fetestexcept(ALL_STD_EXCEPT) == 0); diff --git a/tools/regression/lib/msun/test-next.c b/tools/regression/lib/msun/test-next.c index 68e4361..d16fa77 100644 --- a/tools/regression/lib/msun/test-next.c +++ b/tools/regression/lib/msun/test-next.c @@ -41,8 +41,8 @@ __FBSDID("$FreeBSD$"); #include <ieeefp.h> #endif -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID |\ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" + #define test(exp, ans, ex) do { \ double __ans = (ans); \ feclearexcept(ALL_STD_EXCEPT); \ @@ -235,7 +235,7 @@ _testl(const char *exp, int line, long double actual, long double expected, int actual_except; actual_except = fetestexcept(ALL_STD_EXCEPT); - if (actual != expected && !(isnan(actual) && isnan(expected))) { + if (!fpequal(actual, expected)) { fprintf(stderr, "%d: %s returned %La, expecting %La\n", line, exp, actual, expected); abort(); diff --git a/tools/regression/lib/msun/test-rem.c b/tools/regression/lib/msun/test-rem.c index 840bea3..36e3476 100644 --- a/tools/regression/lib/msun/test-rem.c +++ b/tools/regression/lib/msun/test-rem.c @@ -67,8 +67,8 @@ main(int argc, char *argv[]) test(4, 4, 0, 1); test(0, 3.0, 0, 0); - testd(0x1p-1074, 1, 0x1p-1074, 0x1p-1074); - testf(0x1p-149, 1, 0x1p-149, 0x1p-149); + testd(0x1p-1074, 1, 0x1p-1074, 0); + testf(0x1p-149, 1, 0x1p-149, 0); test(3.0, 4, -1, 1); test(3.0, -4, -1, -1); testd(275 * 1193040, 275, 0, 1193040); diff --git a/tools/regression/lib/msun/test-trig.c b/tools/regression/lib/msun/test-trig.c index 1ac7873..80f1aef 100644 --- a/tools/regression/lib/msun/test-trig.c +++ b/tools/regression/lib/msun/test-trig.c @@ -42,8 +42,7 @@ __FBSDID("$FreeBSD$"); #include <math.h> #include <stdio.h> -#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ - FE_OVERFLOW | FE_UNDERFLOW) +#include "test-utils.h" #define LEN(a) (sizeof(a) / sizeof((a)[0])) @@ -66,7 +65,7 @@ __FBSDID("$FreeBSD$"); volatile long double _d = x; \ assert(feclearexcept(FE_ALL_EXCEPT) == 0); \ assert(fpequal((func)(_d), (result))); \ - assert(((func), fetestexcept(exceptmask) == (excepts))); \ + assert(((void)(func), fetestexcept(exceptmask) == (excepts))); \ } while (0) #define testall(prefix, x, result, exceptmask, excepts) do { \ @@ -80,19 +79,6 @@ __FBSDID("$FreeBSD$"); test(prefix##f, x, (float)result, exceptmask, excepts); \ } while (0) - - -/* - * Determine whether x and y are equal, with two special rules: - * +0.0 != -0.0 - * NaN == NaN - */ -int -fpequal(long double x, long double y) -{ - return ((x == y && !signbit(x) == !signbit(y)) || isnan(x) && isnan(y)); -} - /* * Test special cases in sin(), cos(), and tan(). */ diff --git a/tools/regression/lib/msun/test-utils.h b/tools/regression/lib/msun/test-utils.h new file mode 100644 index 0000000..bf0d6de --- /dev/null +++ b/tools/regression/lib/msun/test-utils.h @@ -0,0 +1,174 @@ +/*- + * Copyright (c) 2005-2013 David Schultz <das@FreeBSD.org> + * 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 _TEST_UTILS_H_ +#define _TEST_UTILS_H_ + +#include <complex.h> +#include <fenv.h> + +/* + * Implementations are permitted to define additional exception flags + * not specified in the standard, so it is not necessarily true that + * FE_ALL_EXCEPT == ALL_STD_EXCEPT. + */ +#define ALL_STD_EXCEPT (FE_DIVBYZERO | FE_INEXACT | FE_INVALID | \ + FE_OVERFLOW | FE_UNDERFLOW) +#define OPT_INVALID (ALL_STD_EXCEPT & ~FE_INVALID) +#define OPT_INEXACT (ALL_STD_EXCEPT & ~FE_INEXACT) +#define FLT_ULP() ldexpl(1.0, 1 - FLT_MANT_DIG) +#define DBL_ULP() ldexpl(1.0, 1 - DBL_MANT_DIG) +#define LDBL_ULP() ldexpl(1.0, 1 - LDBL_MANT_DIG) + +/* + * Flags that control the behavior of various fpequal* functions. + * XXX This is messy due to merging various notions of "close enough" + * that are best suited for different functions. + * + * CS_REAL + * CS_IMAG + * CS_BOTH + * (cfpequal_cs, fpequal_tol, cfpequal_tol) Whether to check the sign of + * the real part of the result, the imaginary part, or both. + * + * FPE_ABS_ZERO + * (fpequal_tol, cfpequal_tol) If set, treats the tolerance as an absolute + * tolerance when the expected value is 0. This is useful when there is + * round-off error in the input, e.g., cos(Pi/2) ~= 0. + */ +#define CS_REAL 0x01 +#define CS_IMAG 0x02 +#define CS_BOTH (CS_REAL | CS_IMAG) +#define FPE_ABS_ZERO 0x04 + +#ifdef DEBUG +#define debug(...) printf(__VA_ARGS__) +#else +#define debug(...) (void)0 +#endif + +/* + * XXX The ancient version of gcc in the base system doesn't support CMPLXL, + * but we can fake it most of the time. + */ +#ifndef CMPLXL +static inline long double complex +CMPLXL(long double x, long double y) +{ + long double complex z; + + __real__ z = x; + __imag__ z = y; + return (z); +} +#endif + +/* + * Compare d1 and d2 using special rules: NaN == NaN and +0 != -0. + * Fail an assertion if they differ. + */ +static int +fpequal(long double d1, long double d2) +{ + + if (d1 != d2) + return (isnan(d1) && isnan(d2)); + return (copysignl(1.0, d1) == copysignl(1.0, d2)); +} + +/* + * Determine whether x and y are equal, with two special rules: + * +0.0 != -0.0 + * NaN == NaN + * If checksign is 0, we compare the absolute values instead. + */ +static int +fpequal_cs(long double x, long double y, int checksign) +{ + if (isnan(x) && isnan(y)) + return (1); + if (checksign) + return (x == y && !signbit(x) == !signbit(y)); + else + return (fabsl(x) == fabsl(y)); +} + +static int +fpequal_tol(long double x, long double y, long double tol, unsigned int flags) +{ + fenv_t env; + int ret; + + if (isnan(x) && isnan(y)) + return (1); + if (!signbit(x) != !signbit(y) && (flags & CS_BOTH)) + return (0); + if (x == y) + return (1); + if (tol == 0) + return (0); + + /* Hard case: need to check the tolerance. */ + feholdexcept(&env); + /* + * For our purposes here, if y=0, we interpret tol as an absolute + * tolerance. This is to account for roundoff in the input, e.g., + * cos(Pi/2) ~= 0. + */ + if ((flags & FPE_ABS_ZERO) && y == 0.0) + ret = fabsl(x - y) <= fabsl(tol); + else + ret = fabsl(x - y) <= fabsl(y * tol); + fesetenv(&env); + return (ret); +} + +static int +cfpequal(long double complex d1, long double complex d2) +{ + + return (fpequal(creall(d1), creall(d2)) && + fpequal(cimagl(d1), cimagl(d2))); +} + +static int +cfpequal_cs(long double complex x, long double complex y, int checksign) +{ + return (fpequal_cs(creal(x), creal(y), checksign) + && fpequal_cs(cimag(x), cimag(y), checksign)); +} + +static int +cfpequal_tol(long double complex x, long double complex y, long double tol, + unsigned int flags) +{ + return (fpequal_tol(creal(x), creal(y), tol, flags) + && fpequal_tol(cimag(x), cimag(y), tol, flags)); +} + +#endif /* _TEST_UTILS_H_ */ diff --git a/tools/regression/pjdfstest/pjdfstest.c b/tools/regression/pjdfstest/pjdfstest.c index fd19084..ceab2dc 100644 --- a/tools/regression/pjdfstest/pjdfstest.c +++ b/tools/regression/pjdfstest/pjdfstest.c @@ -581,13 +581,18 @@ call_syscall(struct syscall_desc *scall, char *argv[]) args[i].str = (void *)0xdeadc0de; else args[i].str = argv[i]; - } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_NUMBER) { + } else if ((scall->sd_args[i] & TYPE_MASK) == + TYPE_NUMBER) { args[i].num = strtoll(argv[i], &endp, 0); - if (*endp != '\0' && !isspace((unsigned char)*endp)) { - fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); + if (*endp != '\0' && + !isspace((unsigned char)*endp)) { + fprintf(stderr, + "invalid argument %u, number expected [%s]\n", + i, endp); exit(1); } - } else if ((scall->sd_args[i] & TYPE_MASK) == TYPE_DESCRIPTOR) { + } else if ((scall->sd_args[i] & TYPE_MASK) == + TYPE_DESCRIPTOR) { if (strcmp(argv[i], "AT_FDCWD") == 0) { args[i].num = AT_FDCWD; } else if (strcmp(argv[i], "BADFD") == 0) { @@ -600,8 +605,11 @@ call_syscall(struct syscall_desc *scall, char *argv[]) int pos; pos = strtoll(argv[i], &endp, 0); - if (*endp != '\0' && !isspace((unsigned char)*endp)) { - fprintf(stderr, "invalid argument %u, number expected [%s]\n", i, endp); + if (*endp != '\0' && + !isspace((unsigned char)*endp)) { + fprintf(stderr, + "invalid argument %u, number expected [%s]\n", + i, endp); exit(1); } args[i].num = descriptor_get(pos); @@ -640,7 +648,8 @@ call_syscall(struct syscall_desc *scall, char *argv[]) fprintf(stderr, "too few arguments\n"); exit(1); } - rval = openat(NUM(0), STR(1), (int)flags, (mode_t)NUM(3)); + rval = openat(NUM(0), STR(1), (int)flags, + (mode_t)NUM(3)); } else { if (i == 4) { fprintf(stderr, "too many arguments\n"); @@ -716,7 +725,7 @@ call_syscall(struct syscall_desc *scall, char *argv[]) } dev = makedev(NUM(fa + 3), NUM(fa + 4)); - if (strcmp(STR(fa + 1), "c") == 0) /* character device */ + if (strcmp(STR(fa + 1), "c") == 0) /* character device */ ntype = S_IFCHR; else if (strcmp(STR(fa + 1), "b") == 0) /* block device */ ntype = S_IFBLK; @@ -988,7 +997,8 @@ set_gids(char *gids) assert(ngroups > 0); gidset = malloc(sizeof(*gidset) * ngroups); assert(gidset != NULL); - for (i = 0, g = strtok(gids, ","); g != NULL; g = strtok(NULL, ","), i++) { + for (i = 0, g = strtok(gids, ","); g != NULL; + g = strtok(NULL, ","), i++) { if (i >= ngroups) { fprintf(stderr, "too many gids\n"); exit(1); @@ -1005,7 +1015,8 @@ set_gids(char *gids) exit(1); } if (setegid(gidset[0]) < 0) { - fprintf(stderr, "cannot change effective gid: %s\n", strerror(errno)); + fprintf(stderr, "cannot change effective gid: %s\n", + strerror(errno)); exit(1); } free(gidset); @@ -1075,7 +1086,8 @@ main(int argc, char *argv[]) for (;;) { scall = find_syscall(argv[0]); if (scall == NULL) { - fprintf(stderr, "syscall '%s' not supported\n", argv[0]); + fprintf(stderr, "syscall '%s' not supported\n", + argv[0]); exit(1); } argc++; diff --git a/tools/regression/priv/Makefile b/tools/regression/priv/Makefile index 663d68d..9ed28a7 100644 --- a/tools/regression/priv/Makefile +++ b/tools/regression/priv/Makefile @@ -45,7 +45,7 @@ SRCS= main.c \ priv_vm_mlock.c \ priv_vm_munlock.c -NO_MAN= +MAN= WARNS?= 3 DPADD+= ${LIBIPSEC} diff --git a/tools/regression/pthread/cv_cancel1/cv_cancel1.c b/tools/regression/pthread/cv_cancel1/cv_cancel1.c index cacad44..2ae94c5 100644 --- a/tools/regression/pthread/cv_cancel1/cv_cancel1.c +++ b/tools/regression/pthread/cv_cancel1/cv_cancel1.c @@ -28,6 +28,7 @@ */ #include <pthread.h> #include <stdio.h> +#include <unistd.h> #define NLOOPS 10 diff --git a/tools/regression/sbin/dhclient/Makefile b/tools/regression/sbin/dhclient/Makefile index 7de3791..a9c876e 100644 --- a/tools/regression/sbin/dhclient/Makefile +++ b/tools/regression/sbin/dhclient/Makefile @@ -11,6 +11,7 @@ LDADD= -lutil PROG= option-domain-search +NO_MAN= WARNS?= 2 .include <bsd.prog.mk> diff --git a/tools/regression/usr.bin/xargs/regress.0.in b/tools/regression/usr.bin/xargs/regress.0.in Binary files differnew file mode 100644 index 0000000..448ba53 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.0.in diff --git a/tools/regression/usr.bin/xargs/regress.0.out b/tools/regression/usr.bin/xargs/regress.0.out new file mode 100644 index 0000000..2bc9725 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.0.out @@ -0,0 +1,8 @@ +quick ' brown +fox jumped +over "the lazy +dog +quick brown fox +jumped over the +lazy dog + diff --git a/tools/regression/usr.bin/xargs/regress.0I.out b/tools/regression/usr.bin/xargs/regress.0I.out new file mode 100644 index 0000000..16009c0 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.0I.out @@ -0,0 +1,18 @@ +The quick ' brown quick ' brownquick ' brown quick ' brown +The fox jumped +over "the lazy fox jumped +over "the lazyfox jumped +over "the lazy fox jumped +over "the lazy +The +The dog +quick brown fox dog +quick brown foxdog +quick brown fox dog +quick brown fox +The jumped over the jumped over thejumped over the jumped over the +The lazy dog + lazy dog +lazy dog + lazy dog + diff --git a/tools/regression/usr.bin/xargs/regress.0J.out b/tools/regression/usr.bin/xargs/regress.0J.out new file mode 100644 index 0000000..69c87f9 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.0J.out @@ -0,0 +1,4 @@ +The quick ' brown fox jumped +over "the lazy dog +quick brown fox jumped over the lazy dog + again. diff --git a/tools/regression/usr.bin/xargs/regress.0L.out b/tools/regression/usr.bin/xargs/regress.0L.out new file mode 100644 index 0000000..2d13fcc --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.0L.out @@ -0,0 +1,6 @@ +quick ' brown fox jumped +over "the lazy +dog +quick brown fox +jumped over the lazy dog + diff --git a/tools/regression/usr.bin/xargs/regress.n1.out b/tools/regression/usr.bin/xargs/regress.n1.out new file mode 100644 index 0000000..77ef6c5 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.n1.out @@ -0,0 +1,8 @@ +quick +brown +fox +jumped +over +the +lazy +dog diff --git a/tools/regression/usr.bin/xargs/regress.n2.out b/tools/regression/usr.bin/xargs/regress.n2.out new file mode 100644 index 0000000..4fa3f55 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.n2.out @@ -0,0 +1,4 @@ +quick brown +fox jumped +over the +lazy dog diff --git a/tools/regression/usr.bin/xargs/regress.n3.out b/tools/regression/usr.bin/xargs/regress.n3.out new file mode 100644 index 0000000..21b2c1e --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.n3.out @@ -0,0 +1,3 @@ +quick brown fox +jumped over the +lazy dog diff --git a/tools/regression/usr.bin/xargs/regress.quotes.in b/tools/regression/usr.bin/xargs/regress.quotes.in new file mode 100644 index 0000000..11388a0 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.quotes.in @@ -0,0 +1,4 @@ +a 'b "c' \'d +e\ f "g ' h" +i\ +j diff --git a/tools/regression/usr.bin/xargs/regress.quotes.out b/tools/regression/usr.bin/xargs/regress.quotes.out new file mode 100644 index 0000000..f79ad41 --- /dev/null +++ b/tools/regression/usr.bin/xargs/regress.quotes.out @@ -0,0 +1,7 @@ +a +b "c +'d +e f +g ' h +i +j diff --git a/tools/regression/usr.bin/xargs/regress.sh b/tools/regression/usr.bin/xargs/regress.sh index 7c8db1d..4edeae4 100644 --- a/tools/regression/usr.bin/xargs/regress.sh +++ b/tools/regression/usr.bin/xargs/regress.sh @@ -1,6 +1,6 @@ # $FreeBSD$ -echo 1..5 +echo 1..13 REGRESSION_START($1) @@ -9,5 +9,13 @@ REGRESSION_TEST(`I', `xargs -I% echo The % % % %% % % < regress.in') REGRESSION_TEST(`J', `xargs -J% echo The % again. < regress.in') REGRESSION_TEST(`L', `xargs -L3 echo < regress.in') REGRESSION_TEST(`R', `xargs -I% -R1 echo The % % % %% % % < regress.in') +REGRESSION_TEST(`n1', `xargs -n1 echo < regress.in') +REGRESSION_TEST(`n2', `xargs -n2 echo < regress.in') +REGRESSION_TEST(`n3', `xargs -n3 echo < regress.in') +REGRESSION_TEST(`0', `xargs -0 -n1 echo < regress.0.in') +REGRESSION_TEST(`0I', `xargs -0 -I% echo The % %% % < regress.0.in') +REGRESSION_TEST(`0J', `xargs -0 -J% echo The % again. < regress.0.in') +REGRESSION_TEST(`0L', `xargs -0 -L2 echo < regress.0.in') +REGRESSION_TEST(`quotes', `xargs -n1 echo < regress.quotes.in') REGRESSION_END() diff --git a/tools/regression/usr.bin/yacc/grammar.y b/tools/regression/usr.bin/yacc/grammar.y index 6755522..a2f1883 100644 --- a/tools/regression/usr.bin/yacc/grammar.y +++ b/tools/regression/usr.bin/yacc/grammar.y @@ -1027,7 +1027,7 @@ extern char *yytext; extern FILE *yyin, *yyout; static int curly; /* number of curly brace nesting levels */ -static int ly_count; /* number of occurances of %% */ +static int ly_count; /* number of occurrences of %% */ static int inc_depth; /* include nesting level */ static SymbolTable *included_files; /* files already included */ static int yy_start = 0; /* start state number */ diff --git a/tools/regression/usr.bin/yacc/regress.08.out b/tools/regression/usr.bin/yacc/regress.08.out index 86e93e7..c86f19f 100644 --- a/tools/regression/usr.bin/yacc/regress.08.out +++ b/tools/regression/usr.bin/yacc/regress.08.out @@ -847,7 +847,7 @@ extern char *yytext; extern FILE *yyin, *yyout; static int curly; /* number of curly brace nesting levels */ -static int ly_count; /* number of occurances of %% */ +static int ly_count; /* number of occurrences of %% */ static int inc_depth; /* include nesting level */ static SymbolTable *included_files; /* files already included */ static int yy_start = 0; /* start state number */ diff --git a/tools/test/dtrace/Makefile b/tools/test/dtrace/Makefile index 5cafb87..c9e9a20 100644 --- a/tools/test/dtrace/Makefile +++ b/tools/test/dtrace/Makefile @@ -159,7 +159,6 @@ NOTWORK+= \ ${TESTSRCDIR}/tst/common/sched/tst.enqueue.d \ ${TESTSRCDIR}/tst/common/sched/tst.oncpu.d \ ${TESTSRCDIR}/tst/common/sched/tst.stackdepth.d \ - ${TESTSRCDIR}/tst/common/sdt/tst.sdtargs.d \ ${TESTSRCDIR}/tst/common/usdt/argmap.d \ ${TESTSRCDIR}/tst/common/usdt/args.d \ ${TESTSRCDIR}/tst/common/usdt/forker.d \ diff --git a/tools/test/hwpmc/pmctest.py b/tools/test/hwpmc/pmctest.py index fb4a977..9265dde 100755 --- a/tools/test/hwpmc/pmctest.py +++ b/tools/test/hwpmc/pmctest.py @@ -51,6 +51,10 @@ import sys import subprocess from subprocess import PIPE +# Use input() for Python version 3 +if sys.version_info[0] == 3: + raw_input = input + # A list of strings that are not really counters, just # name tags that are output by pmccontrol -L notcounter = ["IAF", "IAP", "TSC", "UNC", "UCF", "UCP", "SOFT" ] @@ -87,7 +91,7 @@ def main(): print(result) if (options.wait == True): try: - value = input("next?") + value = raw_input("next?") except EOFError: sys.exit() diff --git a/tools/test/posixshm/shm_test.c b/tools/test/posixshm/shm_test.c index 3ab4732..0ec890a 100644 --- a/tools/test/posixshm/shm_test.c +++ b/tools/test/posixshm/shm_test.c @@ -21,7 +21,7 @@ * Signal handler which does nothing. */ static void -ignoreit(int sig) +ignoreit(int sig __unused) { ; } @@ -29,13 +29,13 @@ ignoreit(int sig) int main(int argc, char **argv) { - char buf[1024], *cp; - int desc, rv; + char buf[1024], *cp, c; + int error, desc, rv; long scval; sigset_t ss; struct sigaction sa; void *region; - size_t psize; + size_t i, psize; #ifndef _POSIX_SHARED_MEMORY_OBJECTS printf("_POSIX_SHARED_MEMORY_OBJECTS is undefined\n"); @@ -118,14 +118,29 @@ main(int argc, char **argv) sigemptyset(&ss); sigsuspend(&ss); - for (cp = region; cp < (char *)region + psize; cp++) + for (cp = region; cp < (char *)region + psize; cp++) { if (*cp != '\151') _exit(1); + } + if (lseek(desc, 0, SEEK_SET) == -1) + _exit(1); + for (i = 0; i < psize; i++) { + error = read(desc, &c, 1); + if (c != '\151') + _exit(1); + } _exit(0); } else { int status; - memset(region, '\151', psize); + memset(region, '\151', psize - 2); + error = pwrite(desc, region, 2, psize - 2); + if (error != 2) { + if (error >= 0) + errx(1, "short write %d", error); + else + err(1, "shmfd write"); + } kill(rv, SIGUSR1); waitpid(rv, &status, 0); diff --git a/tools/tools/README b/tools/tools/README index 1260683..ef05ee0 100644 --- a/tools/tools/README +++ b/tools/tools/README @@ -18,6 +18,7 @@ cxgbetool A tool for the cxgbe(4) driver. cxgbtool A tool for the cxgb(4) driver. diffburst OBSOLETE: equivalent functionality is available via split -p. For example: "split -p ^diff < patchfile". See split(1). +drm Tools specific to the DRM/KMS device drivers. editing Editor modes and the like to help editing FreeBSD code. epfe Extract printing filter examples from printing.sgml. ether_reflect An Ethernet packet reflector for low level testing. diff --git a/tools/tools/ath/Makefile b/tools/tools/ath/Makefile index c4c81ba..99dc588 100644 --- a/tools/tools/ath/Makefile +++ b/tools/tools/ath/Makefile @@ -2,7 +2,7 @@ SUBDIR= arcode athdebug athdecode athkey athpoke athprom athrd athregs SUBDIR+= athstats ath_prom_read athradar athaggrstats -SUBDIR+= ath_ee_v14_print ath_ee_v4k_print ath_ee_9287_print +SUBDIR+= ath_ee_v14_print ath_ee_v4k_print ath_ee_9287_print ath_ee_9300_print SUBDIR+= athsurvey athratestats athspectral .include <bsd.subdir.mk> diff --git a/tools/tools/ath/Makefile.inc b/tools/tools/ath/Makefile.inc index 901844e..85953f2 100644 --- a/tools/tools/ath/Makefile.inc +++ b/tools/tools/ath/Makefile.inc @@ -11,4 +11,5 @@ CFLAGS+=-I${.CURDIR}/../common CFLAGS+=-I${.CURDIR}/../../../../sys CFLAGS+=-I${.CURDIR}/../../../../sys/dev/ath CFLAGS+=-I${.CURDIR}/../../../../sys/dev/ath/ath_hal +CFLAGS+=-I${.CURDIR}/../../../../sys/contrib/dev/ath/ath_hal CFLAGS+=-I${.OBJDIR} diff --git a/tools/tools/ath/ath_ee_9300_print/Makefile b/tools/tools/ath/ath_ee_9300_print/Makefile new file mode 100644 index 0000000..8f37eef --- /dev/null +++ b/tools/tools/ath/ath_ee_9300_print/Makefile @@ -0,0 +1,19 @@ +# $FreeBSD$ + +.PATH: ${.CURDIR}/../../../../sys/dev/ath/ath_hal + +PROG= ath_ee_9300_print +NOMAN= yes +NO_MAN= yes +SRCS= main.c +SRCS+= opt_ah.h +CLEANFILES+= opt_ah.h + +opt_ah.h: + echo "#define AH_DEBUG 1" > opt_ah.h + echo "#define AH_DEBUG_COUNTRY 1" >> opt_ah.h + echo "#define AH_SUPPORT_AR5416 1" >> opt_ah.h + +.include <../Makefile.inc> + +.include <bsd.prog.mk> diff --git a/tools/tools/ath/ath_ee_9300_print/main.c b/tools/tools/ath/ath_ee_9300_print/main.c new file mode 100644 index 0000000..acf646e --- /dev/null +++ b/tools/tools/ath/ath_ee_9300_print/main.c @@ -0,0 +1,229 @@ + +/* + * Copyright (c) 2010-2011 Adrian Chadd, Xenion Pty Ltd. + * + * 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$ + */ + +#include <stdio.h> +#include <stdlib.h> +#include <unistd.h> +#include <string.h> +#include <sys/types.h> +#include <err.h> + +struct ath_hal; + +#include "ar9300/ar9300eep.h" + +static void +eeprom_9300_hdr_print(const uint16_t *buf) +{ + const ar9300_eeprom_t *ee = (ar9300_eeprom_t *) buf; + + printf("| Version: %d, Template: %d, MAC: %02x:%02x:%02x:%02x:%02x:%02x |\n", + ee->eeprom_version, + ee->template_version, + ee->mac_addr[0], + ee->mac_addr[1], + ee->mac_addr[2], + ee->mac_addr[3], + ee->mac_addr[4], + ee->mac_addr[5]); +} + +static void +eeprom_9300_base_print(const uint16_t *buf) +{ + const ar9300_eeprom_t *ee = (ar9300_eeprom_t *) buf; + const OSPREY_BASE_EEP_HEADER *ee_base = &ee->base_eep_header; + + printf("| RegDomain: 0x%02x 0x%02x TxRxMask: 0x%02x OpFlags: 0x%02x OpMisc: 0x%02x |\n", + ee_base->reg_dmn[0], + ee_base->reg_dmn[1], + ee_base->txrx_mask, + ee_base->op_cap_flags.op_flags, + ee_base->op_cap_flags.eepMisc); + + printf("| RfSilent: 0x%02x BtOptions: 0x%02x DeviceCap: 0x%02x DeviceType: 0x%02x |\n", + ee_base->rf_silent, + ee_base->blue_tooth_options, + ee_base->device_cap, + ee_base->device_type); + + printf("| pwrTableOffset: %d dB, feature_enable: 0x%02x MiscConfig: 0x%02x |\n", + ee_base->pwrTableOffset, + ee_base->feature_enable, + ee_base->misc_configuration); + + printf("| EepromWriteGpio: %d, WlanDisableGpio: %d, WlanLedGpio: %d RxBandSelectGpio: %d |\n", + ee_base->eeprom_write_enable_gpio, + ee_base->wlan_disable_gpio, + ee_base->wlan_led_gpio, + ee_base->rx_band_select_gpio); + + printf("| TxRxGain: %d, SwReg: %d |\n", + ee_base->txrxgain, + ee_base->swreg); +} + +static void +eeprom_9300_modal_print(const OSPREY_MODAL_EEP_HEADER *m) +{ + int i; + + printf("| AntCtrl: 0x%08x AntCtrl2: 0x%08x |\n", + m->ant_ctrl_common, + m->ant_ctrl_common2); + + for (i = 0; i < OSPREY_MAX_CHAINS; i++) { + printf("| Ch %d: AntCtrl: 0x%08x Atten1: %d, atten1_margin: %d, NfThresh: %d |\n", + i, + m->ant_ctrl_chain[i], + m->xatten1_db[i], + m->xatten1_margin[i], + m->noise_floor_thresh_ch[i]); + } + + printf("| Spur: "); + for (i = 0; i < OSPREY_EEPROM_MODAL_SPURS; i++) { + printf("(%d: %d) ", i, m->spur_chans[i]); + } + printf("|\n"); + + printf("| TempSlope: %d, VoltSlope: %d, QuickDrop: %d, XpaBiasLvl %d |\n", + m->temp_slope, + m->voltSlope, + m->quick_drop, + m->xpa_bias_lvl); + + printf("| txFrameToDataStart: %d, TxFrameToPaOn: %d, TxEndToXpaOff: %d, TxEndToRxOn: %d, TxFrameToXpaOn: %d |\n", + m->tx_frame_to_data_start, + m->tx_frame_to_pa_on, + m->tx_end_to_xpa_off, + m->txEndToRxOn, + m->tx_frame_to_xpa_on); + + printf("| txClip: %d, AntGain: %d, SwitchSettling: %d, adcDesiredSize: %d |\n", + m->txClip, + m->antenna_gain, + m->switchSettling, + m->adcDesiredSize); + + printf("| Thresh62: %d, PaprdMaskHt20: 0x%08x, PaPrdMaskHt40: 0x%08x |\n", + m->thresh62, + m->paprd_rate_mask_ht20, + m->paprd_rate_mask_ht40); + + printf("| SwitchComSpdt: %02x, XlnaBiasStrength: %d, RfGainCap: %d, TxGainCap: %x\n", + m->switchcomspdt, + m->xLNA_bias_strength, + m->rf_gain_cap, + m->tx_gain_cap); + +#if 0 + u_int8_t reserved[MAX_MODAL_RESERVED]; + u_int16_t switchcomspdt; + u_int8_t xLNA_bias_strength; // bit: 0,1:chain0, 2,3:chain1, 4,5:chain2 + u_int8_t rf_gain_cap; + u_int8_t tx_gain_cap; // bit0:4 txgain cap, txgain index for max_txgain + 20 (10dBm higher than max txgain) + u_int8_t futureModal[MAX_MODAL_FUTURE]; + // last 12 bytes stolen and moved to newly created base extension structure +#endif +} + +static void +load_eeprom_dump(const char *file, uint16_t *buf) +{ + unsigned int r[8]; + FILE *fp; + char b[1024]; + int i; + + fp = fopen(file, "r"); + if (!fp) + err(1, "fopen"); + + while (!feof(fp)) { + if (fgets(b, 1024, fp) == NULL) + break; + if (feof(fp)) + break; + if (strlen(b) > 0) + b[strlen(b)-1] = '\0'; + if (strlen(b) == 0) + break; + sscanf(b, "%x: %x %x %x %x %x %x %x %x\n", + &i, &r[0], &r[1], &r[2], &r[3], &r[4], + &r[5], &r[6], &r[7]); + buf[i++] = r[0]; + buf[i++] = r[1]; + buf[i++] = r[2]; + buf[i++] = r[3]; + buf[i++] = r[4]; + buf[i++] = r[5]; + buf[i++] = r[6]; + buf[i++] = r[7]; + } + fclose(fp); +} + +void +usage(char *argv[]) +{ + printf("Usage: %s <eeprom dump file>\n", argv[0]); + printf("\n"); + printf(" The eeprom dump file is a text hexdump of an EEPROM.\n"); + printf(" The lines must be formatted as follows:\n"); + printf(" 0xAAAA: 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD 0xDD\n"); + printf(" where each line must have exactly eight data bytes.\n"); + exit(127); +} + +int +main(int argc, char *argv[]) +{ + uint16_t *eep = NULL; + const ar9300_eeprom_t *ee; + + eep = calloc(4096, sizeof(int16_t)); + + if (argc < 2) + usage(argv); + + load_eeprom_dump(argv[1], eep); + ee = (ar9300_eeprom_t *) eep; + + eeprom_9300_hdr_print(eep); + eeprom_9300_base_print(eep); + + printf("\n2GHz modal:\n"); + eeprom_9300_modal_print(&ee->modal_header_2g); + + printf("\n5GHz modal:\n"); + eeprom_9300_modal_print(&ee->modal_header_5g); + + free(eep); + exit(0); +} diff --git a/tools/tools/ath/athalq/Makefile b/tools/tools/ath/athalq/Makefile index 60c9bf8..a7eb394 100644 --- a/tools/tools/ath/athalq/Makefile +++ b/tools/tools/ath/athalq/Makefile @@ -3,8 +3,10 @@ PROG= athalq NOMAN= yes +CFLAGS+= -I../../../../sys/contrib + SRCS= main.c ar5210_ds.c ar5211_ds.c ar5212_ds.c ar5416_ds.c tdma.c -# SRCS+= ar9300_ds.c +SRCS+= ar9300_ds.c .include <../Makefile.inc> diff --git a/tools/tools/ath/athalq/ar9300_ds.c b/tools/tools/ath/athalq/ar9300_ds.c index 5ab55ca..04455d3 100644 --- a/tools/tools/ath/athalq/ar9300_ds.c +++ b/tools/tools/ath/athalq/ar9300_ds.c @@ -29,7 +29,7 @@ __FBSDID("$FreeBSD$"); #include <sys/endian.h> #include <dev/ath/if_ath_alq.h> -#include <dev/ath/ath_hal/ar9003/ar9300desc.h> +#include <dev/ath/ath_hal/ar9300/ar9300desc.h> #include "ar9300_ds.h" diff --git a/tools/tools/ath/athalq/main.c b/tools/tools/ath/athalq/main.c index 1d5447d..c5ba9ef 100644 --- a/tools/tools/ath/athalq/main.c +++ b/tools/tools/ath/athalq/main.c @@ -30,7 +30,7 @@ __FBSDID("$FreeBSD$"); #include <dev/ath/if_ath_alq.h> -#if 0 +#if 1 #include "ar9300_ds.h" #endif #include "ar5210_ds.h" @@ -75,6 +75,36 @@ ath_alq_print_intr_status(struct if_ath_alq_payload *a) be32toh(is.intr_status)); } +static void +ath_alq_print_beacon_miss(struct if_ath_alq_payload *a) +{ + + printf("[%u.%06u] [%llu] BMISS\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid)); +} + +static void +ath_alq_print_beacon_stuck(struct if_ath_alq_payload *a) +{ + + printf("[%u.%06u] [%llu] BSTUCK\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid)); +} + +static void +ath_alq_print_beacon_resume(struct if_ath_alq_payload *a) +{ + + printf("[%u.%06u] [%llu] BRESUME\n", + (unsigned int) be32toh(a->hdr.tstamp_sec), + (unsigned int) be32toh(a->hdr.tstamp_usec), + (unsigned long long) be64toh(a->hdr.threadid)); +} + int main(int argc, const char *argv[]) { @@ -147,6 +177,15 @@ main(int argc, const char *argv[]) case ATH_ALQ_INTR_STATUS: ath_alq_print_intr_status(a); break; + case ATH_ALQ_MISSED_BEACON: + ath_alq_print_beacon_miss(a); + break; + case ATH_ALQ_STUCK_BEACON: + ath_alq_print_beacon_stuck(a); + break; + case ATH_ALQ_RESUME_BEACON: + ath_alq_print_beacon_resume(a); + break; default: if (be32toh(hdr.sc_hal_magic) == AR5210_MAGIC) ar5210_alq_payload(a); @@ -156,7 +195,7 @@ main(int argc, const char *argv[]) ar5212_alq_payload(a); else if (be32toh(hdr.sc_hal_magic) == AR5416_MAGIC) ar5416_alq_payload(a); -#if 0 +#if 1 else if (be32toh(hdr.sc_hal_magic) == AR9300_MAGIC) ar9300_alq_payload(a); #endif diff --git a/tools/tools/ath/athalq/txdiff.pl b/tools/tools/ath/athalq/txdiff.pl new file mode 100755 index 0000000..dff9405 --- /dev/null +++ b/tools/tools/ath/athalq/txdiff.pl @@ -0,0 +1,34 @@ +#!/usr/bin/perl -w + +use strict; + +# $FreeBSD$ + +# [1360537229.753890] [100494] TXD +# [1360537229.754292] [100494] TXSTATUS: TxDone=1, TS=0x5ccfa5c7 + +my ($tv_sec) = 0; +my ($tv_usec) = 0; + +sub tvdiff($$$$) { + my ($tv1_sec, $tv1_usec, $tv2_sec, $tv2_usec) = @_; + + if ($tv2_usec < $tv1_usec) { + $tv2_usec += 1000000; + $tv1_sec = $tv1_sec + 1; + } + + return ($tv2_sec - $tv1_sec) * 1000000 + ($tv2_usec - $tv1_usec); +} + +while (<>) { + chomp; + m/^\[(.*?)\.(.*?)\]/ || next; + printf "%d\t| %s\n", tvdiff($tv_sec, $tv_usec, $1, $2), $_; +# if (tvdiff($tv_sec, $tv_usec, $1, $2) > 500) { +# printf "%d\t| %s\n", tvdiff($tv_sec, $tv_usec, $1, $2), $_; +# } + $tv_sec = $1; + $tv_usec = $2; +} + diff --git a/tools/tools/ath/athspectral/athspectral.c b/tools/tools/ath/athspectral/athspectral.c index 7bdfa2b..1ec9085 100644 --- a/tools/tools/ath/athspectral/athspectral.c +++ b/tools/tools/ath/athspectral/athspectral.c @@ -67,7 +67,7 @@ spectral_opendev(struct spectralhandler *spectral, const char *devid) spectral->atd.ad_out_data = (caddr_t) &revs; spectral->atd.ad_out_size = sizeof(revs); if (ioctl(spectral->s, SIOCGATHDIAG, &spectral->atd) < 0) { - warn(spectral->atd.ad_name); + warn("%s", spectral->atd.ad_name); return 0; } spectral->ah_devid = revs.ah_devid; @@ -116,7 +116,7 @@ spectralset(struct spectralhandler *spectral, int op, u_int32_t param) spectral->atd.ad_in_data = (caddr_t) &pe; spectral->atd.ad_in_size = sizeof(HAL_SPECTRAL_PARAM); if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) - err(1, spectral->atd.ad_name); + err(1, "%s", spectral->atd.ad_name); } static void @@ -133,7 +133,7 @@ spectral_get(struct spectralhandler *spectral) spectral->atd.ad_out_size = sizeof(pe); if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) - err(1, spectral->atd.ad_name); + err(1, "%s", spectral->atd.ad_name); printf("Spectral parameters (raw):\n"); printf(" ss_enabled: %d\n", pe.ss_enabled); @@ -163,7 +163,7 @@ spectral_start(struct spectralhandler *spectral) spectral->atd.ad_out_size = sizeof(pe); if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) - err(1, spectral->atd.ad_name); + err(1, "%s", spectral->atd.ad_name); } static void @@ -184,7 +184,7 @@ spectral_stop(struct spectralhandler *spectral) spectral->atd.ad_out_size = sizeof(pe); if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) - err(1, spectral->atd.ad_name); + err(1, "%s", spectral->atd.ad_name); } static void @@ -207,7 +207,7 @@ spectral_enable_at_reset(struct spectralhandler *spectral, int val) printf("%s: val=%d\n", __func__, v); if (ioctl(spectral->s, SIOCGATHSPECTRAL, &spectral->atd) < 0) - err(1, spectral->atd.ad_name); + err(1, "%s", spectral->atd.ad_name); } static int diff --git a/tools/tools/ath/athstats/athstats.c b/tools/tools/ath/athstats/athstats.c index 2cffe34..f3f18f4 100644 --- a/tools/tools/ath/athstats/athstats.c +++ b/tools/tools/ath/athstats/athstats.c @@ -262,7 +262,9 @@ static const struct fmt athstats[] = { { 10, "rxdescbusy", "rxdescbusy", "Decryption engine busy" }, #define S_RX_HI_CHAIN AFTER(S_RX_DECRYPT_BUSY_ERR) { 4, "rxhi", "rxhi", "Frames received with RX chain in high power mode" }, -#define S_TX_HTPROTECT AFTER(S_RX_HI_CHAIN) +#define S_RX_STBC AFTER(S_RX_HI_CHAIN) + { 6, "rxstbc", "rxstbc", "Frames received w/ STBC encoding" }, +#define S_TX_HTPROTECT AFTER(S_RX_STBC) { 7, "txhtprot", "txhtprot", "Frames transmitted with HT Protection" }, #define S_RX_QEND AFTER(S_TX_HTPROTECT) { 7, "rxquend", "rxquend", "Hit end of RX descriptor queue" }, @@ -420,7 +422,6 @@ static const struct fmt athstats[] = { { 4, "signal", "sig", "avg recv signal (dBm)" }, #define S_BMISSCOUNT AFTER(S_RX_SIGNAL) { 8, "bmisscount", "bmisscnt", "beacon miss count" }, - }; #define S_PHY_MIN S_RX_PHY_UNDERRUN #define S_PHY_MAX S_RX_PHY_CCK_RESTART @@ -773,6 +774,7 @@ ath_get_curstat(struct statfoo *sf, int s, char b[], size_t bs) case S_RX_POST_CRC_ERR: STAT(rx_post_crc_err); case S_RX_DECRYPT_BUSY_ERR: STAT(rx_decrypt_busy_err); case S_RX_HI_CHAIN: STAT(rx_hi_rx_chain); + case S_RX_STBC: STAT(rx_stbc); case S_TX_HTPROTECT: STAT(tx_htprotect); case S_RX_QEND: STAT(rx_hitqueueend); case S_TX_TIMEOUT: STAT(tx_timeout); @@ -1015,6 +1017,7 @@ ath_get_totstat(struct statfoo *sf, int s, char b[], size_t bs) case S_RX_POST_CRC_ERR: STAT(rx_post_crc_err); case S_RX_DECRYPT_BUSY_ERR: STAT(rx_decrypt_busy_err); case S_RX_HI_CHAIN: STAT(rx_hi_rx_chain); + case S_RX_STBC: STAT(rx_stbc); case S_TX_HTPROTECT: STAT(tx_htprotect); case S_RX_QEND: STAT(rx_hitqueueend); case S_TX_TIMEOUT: STAT(tx_timeout); diff --git a/tools/tools/bootparttest/bootparttest.c b/tools/tools/bootparttest/bootparttest.c index 2b93ee0..f0fb8a9 100644 --- a/tools/tools/bootparttest/bootparttest.c +++ b/tools/tools/bootparttest/bootparttest.c @@ -54,7 +54,7 @@ diskread(void *arg, void *buf, size_t blocks, off_t offset) struct disk *dp; dp = (struct disk *)arg; - printf("%s: read %d blocks from the offset %jd [+%jd]\n", dp->name, + printf("%s: read %lu blocks from the offset %jd [+%jd]\n", dp->name, blocks, offset, dp->offset); if (offset >= dp->mediasize / dp->sectorsize) return (-1); diff --git a/tools/tools/bus_autoconf/bus_load_file.c b/tools/tools/bus_autoconf/bus_load_file.c index 527e5bc..8d82ac3 100644 --- a/tools/tools/bus_autoconf/bus_load_file.c +++ b/tools/tools/bus_autoconf/bus_load_file.c @@ -39,7 +39,7 @@ void load_file(const char *fname, uint8_t **pptr, uint32_t *plen) { uint8_t *ptr; - uint32_t len; + ssize_t len; off_t off; int f; diff --git a/tools/tools/crypto/ipsecstats.c b/tools/tools/crypto/ipsecstats.c index 6ecc1f4..9f98ea8 100644 --- a/tools/tools/crypto/ipsecstats.c +++ b/tools/tools/crypto/ipsecstats.c @@ -25,11 +25,12 @@ * * $FreeBSD$ */ -#include <stdio.h> #include <sys/types.h> #include <netipsec/ipsec.h> #include <netipsec/ah_var.h> #include <netipsec/esp_var.h> +#include <stdint.h> +#include <stdio.h> struct alg { int a; @@ -82,7 +83,7 @@ algname(int a, const struct alg algs[], int nalgs) int main(int argc, char *argv[]) { -#define STAT(x,fmt) if (x) printf(fmt "\n", x) +#define STAT(x,fmt) if (x) printf(fmt "\n", (uintmax_t)x) struct ipsecstat ips; struct ahstat ahs; struct espstat esps; @@ -99,8 +100,7 @@ main(int argc, char *argv[]) if (sysctlbyname("net.inet.esp.stats", &esps, &slen, NULL, NULL) < 0) err(1, "net.inet.esp.stats"); -#define AHSTAT(x,fmt) if (x) printf("ah " fmt ": %u\n", x) -#define AHSTAT64(x,fmt) if (x) printf("ah " fmt ": %llu\n", x) +#define AHSTAT(x,fmt) if (x) printf("ah " fmt ": %ju\n", (uintmax_t)x) AHSTAT(ahs.ahs_input, "input packets processed"); AHSTAT(ahs.ahs_output, "output packets processed"); AHSTAT(ahs.ahs_hdrops, "headers too short"); @@ -120,17 +120,15 @@ main(int argc, char *argv[]) AHSTAT(ahs.ahs_tunnel, "tunnel sanity check failures"); for (i = 0; i < AH_ALG_MAX; i++) if (ahs.ahs_hist[i]) - printf("ah packets with %s: %u\n" + printf("ah packets with %s: %ju\n" , algname(i, aalgs, N(aalgs)) - , ahs.ahs_hist[i] + , (uintmax_t)ahs.ahs_hist[i] ); - AHSTAT64(ahs.ahs_ibytes, "bytes received"); - AHSTAT64(ahs.ahs_obytes, "bytes transmitted"); -#undef AHSTAT64 + AHSTAT(ahs.ahs_ibytes, "bytes received"); + AHSTAT(ahs.ahs_obytes, "bytes transmitted"); #undef AHSTAT -#define ESPSTAT(x,fmt) if (x) printf("esp " fmt ": %u\n", x) -#define ESPSTAT64(x,fmt) if (x) printf("esp " fmt ": %llu\n", x) +#define ESPSTAT(x,fmt) if (x) printf("esp " fmt ": %ju\n", (uintmax_t)x) ESPSTAT(esps.esps_input, "input packets processed"); ESPSTAT(esps.esps_output, "output packets processed"); ESPSTAT(esps.esps_hdrops, "headers too short"); @@ -151,29 +149,30 @@ main(int argc, char *argv[]) ESPSTAT(esps.esps_tunnel, "tunnel sanity check failures"); for (i = 0; i < ESP_ALG_MAX; i++) if (esps.esps_hist[i]) - printf("esp packets with %s: %u\n" + printf("esp packets with %s: %ju\n" , algname(i, espalgs, N(espalgs)) - , esps.esps_hist[i] + , (uintmax_t)esps.esps_hist[i] ); - ESPSTAT64(esps.esps_ibytes, "bytes received"); - ESPSTAT64(esps.esps_obytes, "bytes transmitted"); -#undef ESPSTAT64 + ESPSTAT(esps.esps_ibytes, "bytes received"); + ESPSTAT(esps.esps_obytes, "bytes transmitted"); #undef ESPSTAT printf("\n"); if (ips.ips_in_polvio+ips.ips_out_polvio) - printf("policy violations: input %u output %u\n", - ips.ips_in_polvio, ips.ips_out_polvio); - STAT(ips.ips_out_nosa, "no SA found %u (output)"); - STAT(ips.ips_out_nomem, "no memory available %u (output)"); - STAT(ips.ips_out_noroute, "no route available %u (output)"); - STAT(ips.ips_out_inval, "generic error %u (output)"); - STAT(ips.ips_out_bundlesa, "bundled SA processed %u (output)"); - printf("m_clone processing: %u mbufs + %u clusters coalesced\n", - ips.ips_mbcoalesced, ips.ips_clcoalesced); - printf("m_clone processing: %u clusters copied\n", ips.ips_clcopied); - printf("m_makespace: %u mbufs inserted\n", ips.ips_mbinserted); - printf("header position [front/middle/end]: %u/%u/%u\n", - ips.ips_input_front, ips.ips_input_middle, ips.ips_input_end); + printf("policy violations: input %ju output %ju\n", + (uintmax_t)ips.ips_in_polvio, + (uintmax_t)ips.ips_out_polvio); + STAT(ips.ips_out_nosa, "no SA found %ju (output)"); + STAT(ips.ips_out_nomem, "no memory available %ju (output)"); + STAT(ips.ips_out_noroute, "no route available %ju (output)"); + STAT(ips.ips_out_inval, "generic error %ju (output)"); + STAT(ips.ips_out_bundlesa, "bundled SA processed %ju (output)"); + printf("m_clone processing: %ju mbufs + %ju clusters coalesced\n", + (uintmax_t)ips.ips_mbcoalesced, (uintmax_t)ips.ips_clcoalesced); + STAT(ips.ips_clcopied, "m_clone processing: %ju clusters copied\n"); + STAT(ips.ips_mbinserted, "m_makespace: %ju mbufs inserted\n"); + printf("header position [front/middle/end]: %ju/%ju/%ju\n", + (uintmax_t)ips.ips_input_front, (uintmax_t)ips.ips_input_middle, + (uintmax_t)ips.ips_input_end); return 0; } diff --git a/tools/tools/cxgbetool/cxgbetool.c b/tools/tools/cxgbetool/cxgbetool.c index 6b90b12..e5704e7 100644 --- a/tools/tools/cxgbetool/cxgbetool.c +++ b/tools/tools/cxgbetool/cxgbetool.c @@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$"); #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; @@ -98,6 +99,9 @@ usage(FILE *fp) "\tregdump [<module>] ... dump registers\n" "\tstdio interactive mode\n" "\ttcb <tid> read TCB\n" + "\ttracer <idx> tx<n>|rx<n> set and enable a tracer)\n" + "\ttracer <idx> disable|enable disable or enable a tracer\n" + "\ttracer list list all tracers\n" ); } @@ -122,6 +126,7 @@ real_doit(unsigned long cmd, void *data, const char *cmdstr) rc = errno; return (rc); } + chip_id = nexus[1] - '0'; } rc = ioctl(fd, cmd, data); @@ -965,6 +970,7 @@ set_filter(uint32_t idx, int argc, const char *argv[]) }; 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]; @@ -1361,6 +1367,15 @@ show_sge_context(const struct t4_sge_context *p) FIELD("CngChMap:", 0, 3), { NULL } }; + static struct field_desc t5_conm[] = { + FIELD1("CngMPSEnable:", 21), + FIELD("CngTPMode:", 19, 20), + FIELD1("CngDBPHdr:", 18), + FIELD1("CngDBPData:", 17), + FIELD1("CngIMSG:", 16), + FIELD("CngChMap:", 0, 15), + { NULL } + }; if (p->mem_id == SGE_CONTEXT_EGRESS) show_struct(p->data, 6, (p->data[0] & 2) ? fl : egress); @@ -1369,7 +1384,7 @@ show_sge_context(const struct t4_sge_context *p) else if (p->mem_id == SGE_CONTEXT_INGRESS) show_struct(p->data, 5, ingress); else if (p->mem_id == SGE_CONTEXT_CNM) - show_struct(p->data, 1, conm); + show_struct(p->data, 1, chip_id == 5 ? t5_conm : conm); } #undef FIELD @@ -1657,6 +1672,203 @@ clearstats(int argc, const char *argv[]) } 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<n> or rx<n>."); + return (EINVAL); + } + + len = strlen(argv[0]); + if (len != 3) { + warnx("argument must be 3 characters (tx<n> or rx<n>)"); + 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<n> or rx<n>", 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(); + } + + /* <idx> ... */ + 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; + + /* <idx> disable */ + if (argc == 2 && strcmp(argv[1], "disable") == 0) + return tracer_onoff(idx, 0); + + /* <idx> enable */ + if (argc == 2 && strcmp(argv[1], "enable") == 0) + return tracer_onoff(idx, 1); + + /* <idx> ... */ + return set_tracer(idx, argc - 1, argv + 1); +} + +static int run_cmd(int argc, const char *argv[]) { int rc = -1; @@ -1686,6 +1898,8 @@ run_cmd(int argc, const char *argv[]) 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 { rc = EINVAL; warnx("invalid command \"%s\"", cmd); diff --git a/tools/tools/drm/README b/tools/tools/drm/README new file mode 100644 index 0000000..35660ed --- /dev/null +++ b/tools/tools/drm/README @@ -0,0 +1,5 @@ +# $FreeBSD$ + +gen-drm_pciids Generate drm_pciids.h based on Linux' drm_pciids.h, FreeBSD's + drm_pciids.h and misc/pciids database. +radeon Tools specific to the Radeon device driver. diff --git a/tools/tools/drm/gen-drm_pciids b/tools/tools/drm/gen-drm_pciids new file mode 100755 index 0000000..02ed562 --- /dev/null +++ b/tools/tools/drm/gen-drm_pciids @@ -0,0 +1,183 @@ +#!/usr/bin/perl +# $FreeBSD$ + +use strict; +use warnings; +use utf8; + +use File::Basename; + +my $progname = basename($0); + +sub parse_linux_header ($) +{ + my ($header) = @_; + + open(my $fh, '<', $header) or die "Can't open Linux header: $!\n"; + + my $in_list = 0; + + my %pciids = (); + + my $current_vendor_define; + + while (my $line = <$fh>) { + if ($line =~ /^#define +([^ ]+) +/) { + $current_vendor_define = $1; + $pciids{$current_vendor_define} = {}; + } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}),[^,]+,[^,]+,[^,]+,[^,]+, *([^}]+)\}/) { + my $vendor_id = uc($1); + my $device_id = uc($2); + my $flags = $3; + + $pciids{$current_vendor_define}{$device_id} = { + 'vendor_id' => $vendor_id, + 'flags' => $flags + }; + } + } + + close($fh); + + return %pciids; +} + +sub parse_freebsd_header ($) { + my ($header) = @_; + + open(my $fh, '<', $header) or die "Can't open FreeBSD header: $!\n"; + + my $in_list = 0; + + my %pciids = (); + + my $current_vendor_define; + + while (my $line = <$fh>) { + if ($line =~ /^#define +([^ ]+) +/) { + $current_vendor_define = $1; + $pciids{$current_vendor_define} = {}; + } elsif ($line =~ /^\t\{0x([0-9a-fA-F]{4}), *0x([0-9a-fA-F]{4}), *([^,]+), *"([^"]+)"\}/) { + my $vendor_id = uc($1); + my $device_id = uc($2); + my $flags = $3; + my $name = $4; + + $pciids{$current_vendor_define}{$device_id} = { + 'vendor_id' => $vendor_id, + 'flags' => $flags, + 'name' => $name + }; + } + } + + close($fh); + + return %pciids; +} + +sub parse_pciids_db ($) { + my ($header) = @_; + + open(my $fh, '<', $header) or die "Can't open PCI IDs database: $!\n"; + + my %pciids = (); + + my $current_vendor_id; + + while (my $line = <$fh>) { + if (!$line || $line =~ /^#/) { + next; + } + if ($line =~ /^([0-9a-fA-F]{4}) (.+)/) { + # Vendor ID & name. + my $vendor_id = uc($1); + my $vendor_name = $2; + $pciids{$vendor_id} = { + 'name' => $vendor_name, + 'devices' => {} + }; + + $current_vendor_id = $vendor_id; + } elsif ($line =~ /^\t([0-9a-fA-F]{4}) (.+)/) { + # Device ID & name. + my $device_id = uc($1); + my $device_name = $2; + $pciids{$current_vendor_id}{'devices'}{$device_id} = $device_name; + } + } + + close($fh); + + return %pciids; +} + +if (scalar(@ARGV) != 3) { + print STDERR "Syntax: $progname <linux_header> <freebsd_header> <pciids_db> [<vendor_define>]\n"; + exit 1; +} + +my $linux_header = $ARGV[0]; +my $freebsd_header = $ARGV[1]; +my $pciids_db = $ARGV[2]; +my $only_vendor = $ARGV[3]; + +my %linux_pciids = parse_linux_header($linux_header); +my %freebsd_pciids = parse_freebsd_header($freebsd_header); +my %pciids_db = parse_pciids_db($pciids_db); + +print STDERR "Update FreeBSD's PCI IDs:\n"; +foreach my $vendor_define (sort keys(%linux_pciids)) { + if ($only_vendor && $vendor_define ne $only_vendor) { + print STDERR "(skip unwanted define: $vendor_define)\n"; + next; + } elsif (!$only_vendor && !exists($freebsd_pciids{$vendor_define})) { + print STDERR "(skip unsupport define: $vendor_define)\n"; + next; + } + + foreach my $device_id (sort keys(%{$linux_pciids{$vendor_define}})) { + my $vendor_id = $linux_pciids{$vendor_define}{$device_id}{'vendor_id'}; + + if (exists($freebsd_pciids{$vendor_define}{$device_id})) { + print STDERR " $vendor_define: $vendor_id:$device_id already in header\n"; + next; + } + + my $flags = $linux_pciids{$vendor_define}{$device_id}{'flags'}; + my $name = $pciids_db{$vendor_id}{'devices'}{$device_id} || "Unknown device name"; + print STDERR " $vendor_define: $vendor_id:$device_id is missing ($name)\n"; + $freebsd_pciids{$vendor_define}{$device_id} = { + 'vendor_id' => $vendor_id, + 'flags' => $flags, + 'name' => $name + }; + } +} + +print STDERR "\nWrite FreeBSD header to stdout...\n"; +print <<"EOF"; +/* + * \$FreeBSD\$ + */ + +/* + * Generated by $progname from: + * o previous FreeBSD's drm_pciids.h + * o Linux' drm_pciids.h + * o the PCI ID repository (http://pciids.sourceforge.net/) + * + * See tools/tools/drm/$progname. + */ +EOF +foreach my $vendor_define (sort keys(%freebsd_pciids)) { + print "\n#define $vendor_define \\\n"; + foreach my $device_id (sort keys(%{$freebsd_pciids{$vendor_define}})) { + my $vendor_id = $freebsd_pciids{$vendor_define}{$device_id}{'vendor_id'}; + my $flags = $freebsd_pciids{$vendor_define}{$device_id}{'flags'}; + my $name = $freebsd_pciids{$vendor_define}{$device_id}{'name'}; + + print "\t{0x$vendor_id, 0x$device_id, $flags, \"$name\"}, \\\n"; + } + print "\t{0, 0, 0, NULL}\n"; +} diff --git a/tools/tools/drm/radeon/README b/tools/tools/drm/radeon/README new file mode 100644 index 0000000..a05878e --- /dev/null +++ b/tools/tools/drm/radeon/README @@ -0,0 +1,4 @@ +# $FreeBSD$ + +firmwares Tools to handle Radeon firmwares imported into the tree. +mkregtable Generate headers used to build the Radeon driver. diff --git a/tools/tools/drm/radeon/firmwares/README b/tools/tools/drm/radeon/firmwares/README new file mode 100644 index 0000000..1a28c83 --- /dev/null +++ b/tools/tools/drm/radeon/firmwares/README @@ -0,0 +1,9 @@ +# $FreeBSD$ + +To update firmwares: + + 1. Clone the following Git repository: + git://git.kernel.org/pub/scm/linux/kernel/git/firmware/linux-firmware.git + + 2. Run this script as: + ./encode-firmwares /path/to/linux-firmwares/radeon diff --git a/tools/tools/drm/radeon/firmwares/encode-firmwares b/tools/tools/drm/radeon/firmwares/encode-firmwares new file mode 100755 index 0000000..e95c0d2 --- /dev/null +++ b/tools/tools/drm/radeon/firmwares/encode-firmwares @@ -0,0 +1,17 @@ +#!/bin/sh +# $FreeBSD$ + +set -e + +scriptdir=$(cd $(dirname $0) && pwd) +fwdir="$scriptdir/../../../../../sys/contrib/dev/drm2/radeonkmsfw" +srcdir=$1 + +if [ -z "$srcdir" -o ! -d "$srcdir" ]; then + echo "Syntax: $(basename $0) <path to original firmwares>" 1>&2 + exit +fi + +for file in "$srcdir"/*.bin; do + uuencode -o "$fwdir"/$(basename $file).uu $file $(basename $file) +done diff --git a/tools/tools/drm/radeon/mkregtable/Makefile b/tools/tools/drm/radeon/mkregtable/Makefile new file mode 100644 index 0000000..b83cf5c --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/Makefile @@ -0,0 +1,58 @@ +# $FreeBSD$ + +all: regtables + +PROG= mkregtable + +SRCS= mkregtable.c + +NO_MAN= + +MKREGTABLE= ${PROG} +KERNSRCDIR= ${.CURDIR}/../../../../../sys +REG_SRCS_DIR= ${KERNSRCDIR}/dev/drm2/radeon/reg_srcs +REG_DEST_DIR= ${KERNSRCDIR}/dev/drm2/radeon + +regtables: \ + ${REG_DEST_DIR}/rn50_reg_safe.h \ + ${REG_DEST_DIR}/r100_reg_safe.h \ + ${REG_DEST_DIR}/r200_reg_safe.h \ + ${REG_DEST_DIR}/rv515_reg_safe.h \ + ${REG_DEST_DIR}/r300_reg_safe.h \ + ${REG_DEST_DIR}/r420_reg_safe.h \ + ${REG_DEST_DIR}/rs600_reg_safe.h \ + ${REG_DEST_DIR}/r600_reg_safe.h \ + ${REG_DEST_DIR}/evergreen_reg_safe.h \ + ${REG_DEST_DIR}/cayman_reg_safe.h + +${REG_DEST_DIR}/rn50_reg_safe.h: ${REG_SRCS_DIR}/rn50 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rn50 > $@ + +${REG_DEST_DIR}/r100_reg_safe.h: ${REG_SRCS_DIR}/r100 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r100 > $@ + +${REG_DEST_DIR}/r200_reg_safe.h: ${REG_SRCS_DIR}/r200 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r200 > $@ + +${REG_DEST_DIR}/rv515_reg_safe.h: ${REG_SRCS_DIR}/rv515 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rv515 > $@ + +${REG_DEST_DIR}/r300_reg_safe.h: ${REG_SRCS_DIR}/r300 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r300 > $@ + +${REG_DEST_DIR}/r420_reg_safe.h: ${REG_SRCS_DIR}/r420 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r420 > $@ + +${REG_DEST_DIR}/rs600_reg_safe.h: ${REG_SRCS_DIR}/rs600 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/rs600 > $@ + +${REG_DEST_DIR}/r600_reg_safe.h: ${REG_SRCS_DIR}/r600 ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/r600 > $@ + +${REG_DEST_DIR}/evergreen_reg_safe.h: ${REG_SRCS_DIR}/evergreen ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/evergreen > $@ + +${REG_DEST_DIR}/cayman_reg_safe.h: ${REG_SRCS_DIR}/cayman ${MKREGTABLE} + ./${MKREGTABLE} ${REG_SRCS_DIR}/cayman > $@ + +.include <bsd.prog.mk> diff --git a/tools/tools/drm/radeon/mkregtable/README b/tools/tools/drm/radeon/mkregtable/README new file mode 100644 index 0000000..12b8699 --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/README @@ -0,0 +1,7 @@ +# $FreeBSD$ + +"mkregtable" is a tool used to generate headers for the radeonkms +driver. Headers are regenerated by running "make" in this directory. + +Header source files are in sys/dev/drm2/radeon/reg_srcs. +Generated headers are placed in sys/dev/drm2/radeon. diff --git a/tools/tools/drm/radeon/mkregtable/mkregtable.c b/tools/tools/drm/radeon/mkregtable/mkregtable.c new file mode 100644 index 0000000..51b8f90 --- /dev/null +++ b/tools/tools/drm/radeon/mkregtable/mkregtable.c @@ -0,0 +1,733 @@ +/* utility to create the register check tables + * this includes inlined list.h safe for userspace. + * + * Copyright 2009 Jerome Glisse + * Copyright 2009 Red Hat Inc. + * + * Authors: + * Jerome Glisse + * Dave Airlie + */ + +#include <sys/cdefs.h> +__FBSDID("$FreeBSD$"); + +#include <sys/types.h> +#include <stdlib.h> +#include <string.h> +#include <stdio.h> +#include <regex.h> +#include <libgen.h> + +#define offsetof(TYPE, MEMBER) ((size_t) &((TYPE *)0)->MEMBER) +/** + * container_of - cast a member of a structure out to the containing structure + * @ptr: the pointer to the member. + * @type: the type of the container struct this is embedded in. + * @member: the name of the member within the struct. + * + */ +#define container_of(ptr, type, member) ({ \ + const typeof(((type *)0)->member)*__mptr = (ptr); \ + (type *)((char *)__mptr - offsetof(type, member)); }) + +/* + * Simple doubly linked list implementation. + * + * Some of the internal functions ("__xxx") are useful when + * manipulating whole lists rather than single entries, as + * sometimes we already know the next/prev entries and we can + * generate better code by using them directly rather than + * using the generic single-entry routines. + */ + +struct list_head { + struct list_head *next, *prev; +}; + +#define LIST_HEAD_INIT(name) { &(name), &(name) } + +#define LIST_HEAD(name) \ + struct list_head name = LIST_HEAD_INIT(name) + +static inline void INIT_LIST_HEAD(struct list_head *list) +{ + list->next = list; + list->prev = list; +} + +/* + * Insert a new entry between two known consecutive entries. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +#ifndef CONFIG_DEBUG_LIST +static inline void __list_add(struct list_head *new, + struct list_head *prev, struct list_head *next) +{ + next->prev = new; + new->next = next; + new->prev = prev; + prev->next = new; +} +#else +extern void __list_add(struct list_head *new, + struct list_head *prev, struct list_head *next); +#endif + +/** + * list_add - add a new entry + * @new: new entry to be added + * @head: list head to add it after + * + * Insert a new entry after the specified head. + * This is good for implementing stacks. + */ +static inline void list_add(struct list_head *new, struct list_head *head) +{ + __list_add(new, head, head->next); +} + +/** + * list_add_tail - add a new entry + * @new: new entry to be added + * @head: list head to add it before + * + * Insert a new entry before the specified head. + * This is useful for implementing queues. + */ +static inline void list_add_tail(struct list_head *new, struct list_head *head) +{ + __list_add(new, head->prev, head); +} + +/* + * Delete a list entry by making the prev/next entries + * point to each other. + * + * This is only for internal list manipulation where we know + * the prev/next entries already! + */ +static inline void __list_del(struct list_head *prev, struct list_head *next) +{ + next->prev = prev; + prev->next = next; +} + +/** + * list_del - deletes entry from list. + * @entry: the element to delete from the list. + * Note: list_empty() on entry does not return true after this, the entry is + * in an undefined state. + */ +#ifndef CONFIG_DEBUG_LIST +static inline void list_del(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + entry->next = (void *)0xDEADBEEF; + entry->prev = (void *)0xBEEFDEAD; +} +#else +extern void list_del(struct list_head *entry); +#endif + +/** + * list_replace - replace old entry by new one + * @old : the element to be replaced + * @new : the new element to insert + * + * If @old was empty, it will be overwritten. + */ +static inline void list_replace(struct list_head *old, struct list_head *new) +{ + new->next = old->next; + new->next->prev = new; + new->prev = old->prev; + new->prev->next = new; +} + +static inline void list_replace_init(struct list_head *old, + struct list_head *new) +{ + list_replace(old, new); + INIT_LIST_HEAD(old); +} + +/** + * list_del_init - deletes entry from list and reinitialize it. + * @entry: the element to delete from the list. + */ +static inline void list_del_init(struct list_head *entry) +{ + __list_del(entry->prev, entry->next); + INIT_LIST_HEAD(entry); +} + +/** + * list_move - delete from one list and add as another's head + * @list: the entry to move + * @head: the head that will precede our entry + */ +static inline void list_move(struct list_head *list, struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add(list, head); +} + +/** + * list_move_tail - delete from one list and add as another's tail + * @list: the entry to move + * @head: the head that will follow our entry + */ +static inline void list_move_tail(struct list_head *list, + struct list_head *head) +{ + __list_del(list->prev, list->next); + list_add_tail(list, head); +} + +/** + * list_is_last - tests whether @list is the last entry in list @head + * @list: the entry to test + * @head: the head of the list + */ +static inline int list_is_last(const struct list_head *list, + const struct list_head *head) +{ + return list->next == head; +} + +/** + * list_empty - tests whether a list is empty + * @head: the list to test. + */ +static inline int list_empty(const struct list_head *head) +{ + return head->next == head; +} + +/** + * list_empty_careful - tests whether a list is empty and not being modified + * @head: the list to test + * + * Description: + * tests whether a list is empty _and_ checks that no other CPU might be + * in the process of modifying either member (next or prev) + * + * NOTE: using list_empty_careful() without synchronization + * can only be safe if the only activity that can happen + * to the list entry is list_del_init(). Eg. it cannot be used + * if another CPU could re-list_add() it. + */ +static inline int list_empty_careful(const struct list_head *head) +{ + struct list_head *next = head->next; + return (next == head) && (next == head->prev); +} + +/** + * list_is_singular - tests whether a list has just one entry. + * @head: the list to test. + */ +static inline int list_is_singular(const struct list_head *head) +{ + return !list_empty(head) && (head->next == head->prev); +} + +static inline void __list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + struct list_head *new_first = entry->next; + list->next = head->next; + list->next->prev = list; + list->prev = entry; + entry->next = list; + head->next = new_first; + new_first->prev = head; +} + +/** + * list_cut_position - cut a list into two + * @list: a new list to add all removed entries + * @head: a list with entries + * @entry: an entry within head, could be the head itself + * and if so we won't cut the list + * + * This helper moves the initial part of @head, up to and + * including @entry, from @head to @list. You should + * pass on @entry an element you know is on @head. @list + * should be an empty list or a list you do not care about + * losing its data. + * + */ +static inline void list_cut_position(struct list_head *list, + struct list_head *head, + struct list_head *entry) +{ + if (list_empty(head)) + return; + if (list_is_singular(head) && (head->next != entry && head != entry)) + return; + if (entry == head) + INIT_LIST_HEAD(list); + else + __list_cut_position(list, head, entry); +} + +static inline void __list_splice(const struct list_head *list, + struct list_head *prev, struct list_head *next) +{ + struct list_head *first = list->next; + struct list_head *last = list->prev; + + first->prev = prev; + prev->next = first; + + last->next = next; + next->prev = last; +} + +/** + * list_splice - join two lists, this is designed for stacks + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice(const struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head, head->next); +} + +/** + * list_splice_tail - join two lists, each list being a queue + * @list: the new list to add. + * @head: the place to add it in the first list. + */ +static inline void list_splice_tail(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) + __list_splice(list, head->prev, head); +} + +/** + * list_splice_init - join two lists and reinitialise the emptied list. + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * The list at @list is reinitialised + */ +static inline void list_splice_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head, head->next); + INIT_LIST_HEAD(list); + } +} + +/** + * list_splice_tail_init - join two lists and reinitialise the emptied list + * @list: the new list to add. + * @head: the place to add it in the first list. + * + * Each of the lists is a queue. + * The list at @list is reinitialised + */ +static inline void list_splice_tail_init(struct list_head *list, + struct list_head *head) +{ + if (!list_empty(list)) { + __list_splice(list, head->prev, head); + INIT_LIST_HEAD(list); + } +} + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) \ + container_of(ptr, type, member) + +/** + * list_first_entry - get the first element from a list + * @ptr: the list head to take the element from. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + * + * Note, that list is expected to be not empty. + */ +#define list_first_entry(ptr, type, member) \ + list_entry((ptr)->next, type, member) + +/** + * list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each(pos, head) \ + for (pos = (head)->next; prefetch(pos->next), pos != (head); \ + pos = pos->next) + +/** + * __list_for_each - iterate over a list + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + * + * This variant differs from list_for_each() in that it's the + * simplest possible list iteration code, no prefetching is done. + * Use this for code that knows the list to be very short (empty + * or 1 entry) most of the time. + */ +#define __list_for_each(pos, head) \ + for (pos = (head)->next; pos != (head); pos = pos->next) + +/** + * list_for_each_prev - iterate over a list backwards + * @pos: the &struct list_head to use as a loop cursor. + * @head: the head for your list. + */ +#define list_for_each_prev(pos, head) \ + for (pos = (head)->prev; prefetch(pos->prev), pos != (head); \ + pos = pos->prev) + +/** + * list_for_each_safe - iterate over a list safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_safe(pos, n, head) \ + for (pos = (head)->next, n = pos->next; pos != (head); \ + pos = n, n = pos->next) + +/** + * list_for_each_prev_safe - iterate over a list backwards safe against removal of list entry + * @pos: the &struct list_head to use as a loop cursor. + * @n: another &struct list_head to use as temporary storage + * @head: the head for your list. + */ +#define list_for_each_prev_safe(pos, n, head) \ + for (pos = (head)->prev, n = pos->prev; \ + prefetch(pos->prev), pos != (head); \ + pos = n, n = pos->prev) + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_reverse - iterate backwards over list of given type. + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_reverse(pos, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_prepare_entry - prepare a pos entry for use in list_for_each_entry_continue() + * @pos: the type * to use as a start point + * @head: the head of the list + * @member: the name of the list_struct within the struct. + * + * Prepares a pos entry for use as a start point in list_for_each_entry_continue(). + */ +#define list_prepare_entry(pos, head, member) \ + ((pos) ? : list_entry(head, typeof(*pos), member)) + +/** + * list_for_each_entry_continue - continue iteration over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Continue to iterate over list of given type, continuing after + * the current position. + */ +#define list_for_each_entry_continue(pos, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member); \ + prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_continue_reverse - iterate backwards from the given point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Start to iterate over list of given type backwards, continuing after + * the current position. + */ +#define list_for_each_entry_continue_reverse(pos, head, member) \ + for (pos = list_entry(pos->member.prev, typeof(*pos), member); \ + prefetch(pos->member.prev), &pos->member != (head); \ + pos = list_entry(pos->member.prev, typeof(*pos), member)) + +/** + * list_for_each_entry_from - iterate over list of given type from the current point + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing from current position. + */ +#define list_for_each_entry_from(pos, head, member) \ + for (; prefetch(pos->member.next), &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_continue + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type, continuing after current point, + * safe against removal of list entry. + */ +#define list_for_each_entry_safe_continue(pos, n, head, member) \ + for (pos = list_entry(pos->member.next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_from + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate over list of given type from current point, safe against + * removal of list entry. + */ +#define list_for_each_entry_safe_from(pos, n, head, member) \ + for (n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +/** + * list_for_each_entry_safe_reverse + * @pos: the type * to use as a loop cursor. + * @n: another type * to use as temporary storage + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + * + * Iterate backwards over list of given type, safe against removal + * of list entry. + */ +#define list_for_each_entry_safe_reverse(pos, n, head, member) \ + for (pos = list_entry((head)->prev, typeof(*pos), member), \ + n = list_entry(pos->member.prev, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.prev, typeof(*n), member)) + +struct offset { + struct list_head list; + unsigned offset; +}; + +struct table { + struct list_head offsets; + unsigned offset_max; + unsigned nentry; + unsigned *table; + char *gpu_prefix; +}; + +static struct offset *offset_new(unsigned o) +{ + struct offset *offset; + + offset = (struct offset *)malloc(sizeof(struct offset)); + if (offset) { + INIT_LIST_HEAD(&offset->list); + offset->offset = o; + } + return offset; +} + +static void table_offset_add(struct table *t, struct offset *offset) +{ + list_add_tail(&offset->list, &t->offsets); +} + +static void table_init(struct table *t) +{ + INIT_LIST_HEAD(&t->offsets); + t->offset_max = 0; + t->nentry = 0; + t->table = NULL; +} + +static void table_print(struct table *t) +{ + unsigned nlloop, i, j, n, c, id; + + nlloop = (t->nentry + 3) / 4; + c = t->nentry; + printf( + "#include <sys/cdefs.h>\n" + "__FBSDID(\"$" "FreeBSD" "$\");\n" + "\n" + ); + printf("static const unsigned %s_reg_safe_bm[%d] = {\n", t->gpu_prefix, + t->nentry); + for (i = 0, id = 0; i < nlloop; i++) { + n = 4; + if (n > c) + n = c; + c -= n; + for (j = 0; j < n; j++) { + if (j == 0) + printf("\t"); + else + printf(" "); + printf("0x%08X,", t->table[id++]); + } + printf("\n"); + } + printf("};\n"); +} + +static int table_build(struct table *t) +{ + struct offset *offset; + unsigned i, m; + + t->nentry = ((t->offset_max >> 2) + 31) / 32; + t->table = (unsigned *)malloc(sizeof(unsigned) * t->nentry); + if (t->table == NULL) + return -1; + memset(t->table, 0xff, sizeof(unsigned) * t->nentry); + list_for_each_entry(offset, &t->offsets, list) { + i = (offset->offset >> 2) / 32; + m = (offset->offset >> 2) & 31; + m = 1 << m; + t->table[i] ^= m; + } + return 0; +} + +static char gpu_name[10]; +static int parser_auth(struct table *t, const char *filename) +{ + FILE *file; + regex_t mask_rex; + regmatch_t match[4]; + char buf[1024]; + size_t end; + int len; + int done = 0; + int r; + unsigned o; + struct offset *offset; + char last_reg_s[10]; + int last_reg; + + if (regcomp + (&mask_rex, "(0x[0-9a-fA-F]*) *([_a-zA-Z0-9]*)", REG_EXTENDED)) { + fprintf(stderr, "Failed to compile regular expression\n"); + return -1; + } + file = fopen(filename, "r"); + if (file == NULL) { + fprintf(stderr, "Failed to open: %s\n", filename); + return -1; + } + fseek(file, 0, SEEK_END); + end = ftell(file); + fseek(file, 0, SEEK_SET); + + /* get header */ + if (fgets(buf, 1024, file) == NULL) { + fclose(file); + return -1; + } + + /* first line will contain the last register + * and gpu name */ + sscanf(buf, "%s %s", gpu_name, last_reg_s); + t->gpu_prefix = gpu_name; + last_reg = strtol(last_reg_s, NULL, 16); + + do { + if (fgets(buf, 1024, file) == NULL) { + fclose(file); + return -1; + } + len = strlen(buf); + if (ftell(file) == end) + done = 1; + if (len) { + r = regexec(&mask_rex, buf, 4, match, 0); + if (r == REG_NOMATCH) { + } else if (r) { + fprintf(stderr, + "Error matching regular expression %d in %s\n", + r, filename); + fclose(file); + return -1; + } else { + buf[match[0].rm_eo] = 0; + buf[match[1].rm_eo] = 0; + buf[match[2].rm_eo] = 0; + o = strtol(&buf[match[1].rm_so], NULL, 16); + offset = offset_new(o); + table_offset_add(t, offset); + if (o > t->offset_max) + t->offset_max = o; + } + } + } while (!done); + fclose(file); + if (t->offset_max < last_reg) + t->offset_max = last_reg; + return table_build(t); +} + +int main(int argc, char *argv[]) +{ + struct table t; + + if (argc != 2) { + fprintf(stderr, "Usage: %s <authfile>\n", argv[0]); + exit(1); + } + table_init(&t); + if (parser_auth(&t, argv[1])) { + fprintf(stderr, "Failed to parse file %s\n", argv[1]); + return -1; + } + table_print(&t); + return 0; +} diff --git a/tools/tools/ifinfo/ifinfo.c b/tools/tools/ifinfo/ifinfo.c index f5987f7..bfc3863 100644 --- a/tools/tools/ifinfo/ifinfo.c +++ b/tools/tools/ifinfo/ifinfo.c @@ -169,8 +169,11 @@ printit(const struct ifmibdata *ifmd, const char *dname) ifmd->ifmd_data.ifi_physical)); printf("\taddress length: %d\n", ifmd->ifmd_data.ifi_addrlen); printf("\theader length: %d\n", ifmd->ifmd_data.ifi_hdrlen); - printf("\treceive spare char1: %u\n", ifmd->ifmd_data.ifi_spare_char1); - printf("\ttransmit spare char2: %u\n", ifmd->ifmd_data.ifi_spare_char2); + printf("\tlink state: %u\n", ifmd->ifmd_data.ifi_link_state); + printf("\tvhid: %u\n", ifmd->ifmd_data.ifi_vhid); + printf("\tbaudrate power factor: %u\n", + ifmd->ifmd_data.ifi_baudrate_pf); + printf("\tdatalen: %u\n", ifmd->ifmd_data.ifi_datalen); printf("\tmtu: %lu\n", ifmd->ifmd_data.ifi_mtu); printf("\tmetric: %lu\n", ifmd->ifmd_data.ifi_metric); printf("\tline rate: %lu bit/s\n", ifmd->ifmd_data.ifi_baudrate); @@ -186,6 +189,10 @@ printit(const struct ifmibdata *ifmd, const char *dname) printf("\tinput queue drops: %lu\n", ifmd->ifmd_data.ifi_iqdrops); printf("\tpackets for unknown protocol: %lu\n", ifmd->ifmd_data.ifi_noproto); + printf("\tHW offload capabilities: 0x%lx\n", + ifmd->ifmd_data.ifi_hwassist); + printf("\tuptime at attach or stat reset: %lu\n", + ifmd->ifmd_data.ifi_epoch); #ifdef notdef printf("\treceive timing: %lu usec\n", ifmd->ifmd_data.ifi_recvtiming); printf("\ttransmit timing: %lu usec\n", diff --git a/tools/tools/makeroot/Makefile b/tools/tools/makeroot/Makefile new file mode 100644 index 0000000..ebf81ae --- /dev/null +++ b/tools/tools/makeroot/Makefile @@ -0,0 +1,8 @@ +# $FreeBSD$ + +SCRIPTS= makeroot.sh +MAN= makeroot.8 + +BINDIR?= /usr/sbin + +.include <bsd.prog.mk> diff --git a/tools/tools/makeroot/makeroot.8 b/tools/tools/makeroot/makeroot.8 new file mode 100644 index 0000000..379187c --- /dev/null +++ b/tools/tools/makeroot/makeroot.8 @@ -0,0 +1,131 @@ +.\"- +.\" Copyright (c) 2013 SRI International +.\" All rights reserved. +.\" +.\" This software was developed by SRI International and the University of +.\" Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) +.\" ("CTSRD"), as part of the DARPA CRASH research programme. +.\" +.\" 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$ +.Dd May 20, 2013 +.Dt MAKEROOT 8 +.Os +.Sh NAME +.Nm makeroot +.Nd Tool to create root filesystem images given a tree containing a manifest +.Sh SYNOPSIS +.Nm +.Op Fl d +.Op Fl B Ar byte-order +.Op Fl e Ar extras-manifest +.Op Fl f Ar filelist +.Op Fl k Ar keydir Op Fl K Ar user +.Op Fl p Ar master.passwd Op Fl g Ar group +.Op Fl s Ar size +.Ar image-file +.Ar rootdir +.Sh DESCRIPTION +The +.Nm +script creates a UFS filesystem image into +.Ar imagefile . +By default, +all filesystem objects listed in the +.Pa METALOG +file contained in the +.Ar rootdir +directory will be placed in the root of the UFS image +.Ar image-file . +.Pp +Images can be customized with a number of different flags: +.Bl -tag -width indent +.It Fl B Ar byte-order +Set the byte order of the image to +.Ar byte-order . +This argument is passed directly to +.Xr makefs 8 . +.It Fl d +Enable debugging output. +.It Fl e Ar manifest +Extra files listed in the +.Xr nmtree 8 +format +.Ar manifest +file are added to the filesystem image. +If no contents= tag is specified or a contents= tag is relative then +files are found relative to the basename of the full path of the +manifest. +If a contents= tag is provided and it is an absolute path then the file +will be from that path. +.It Fl f Ar filelist +Constrain set of filesystem objects included from +.Ar rootdir +to those listed (one per line) in the +.Ar filelist +plus any required directories. +.It Fl k Ar keydir Op Fl K Ar user +Create a .ssh/authorized_keys file from a collection of public key files +stored in +.Ar keydir +and install it in the home directory of +.Ar user . +If no +.Fl K +argument is supplied then the files will be installed in the root user's +directory. +.It Fl p Ar master.passwd Op Fl g Ar group +Install an alternate +.Ar master.passwd +file and optionally an alternative +.Ar group +file. +.It Fl s Ar size +Set the size of the image to +.Ar size . +The +.Fl s +argument is passed directly to +.Xr makefs 8 . +.El +.Sh FILES +.Bl -tag -width METALOG -compact +.It Pa METALOG +.Xr mtree 5 +2.0 format manifest of permissions and ownership for files in the root +directory. +This file is generated by installworld, distribution, and installkernel. +.El +.Sh EXAMPLES +.Dl $ makeroot.sh -k keys -K ctsrd -p extras/etc/master.passwd -g extras/etc/group -e extras/mdroot.mtree -e demo/demo.mtree -e extras/ctsrd.mtree -s 26112k -f demo.files cheribsd-demo.img /path/to/dist +.Sh SEE ALSO +.Xr mtree 5 , +.Xr makefs 8 , +.Xr nmtree 8 +.Sh AUTHORS +This software and this manual page were developed by SRI International +and the University of Cambridge Computer Laboratory under DARPA/AFRL +contract +.Pq FA8750-10-C-0237 +.Pq Do CTSRD Dc , +as part of the DARPA CRASH research programme. diff --git a/tools/tools/makeroot/makeroot.sh b/tools/tools/makeroot/makeroot.sh new file mode 100755 index 0000000..3db4e7f --- /dev/null +++ b/tools/tools/makeroot/makeroot.sh @@ -0,0 +1,236 @@ +#!/bin/sh -e +#- +# Copyright (c) 2012-2013 SRI International +# Copyright (c) 2012 Robert N. M. Watson +# All rights reserved. +# +# This software was developed by SRI International and the University of +# Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237) +# ("CTSRD"), as part of the DARPA CRASH research programme. +# +# 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$ + +usage() +{ + cat <<EOF 1>&2 +usage: makeroot.sh [-B byte-order] [-d] [-e <extras manifest>] [-f <filelist>] + [-k <keydir> [-K <user>]] + [-p <master.passwd> [-g <groupfile>]] [-s <size>] + <image> <bsdroot> +EOF + exit 1 +} + +warn() +{ + echo `basename $0` "$@" 1>&2 +} + +err() +{ + ret=$1 + shift + warn "$@" + exit $ret +} + +atexit() +{ + if [ -z "${DEBUG}" ]; then + rm -rf ${tmpdir} + else + warn "temp directory left at ${tmpdir}" + fi +} + +DEBUG= +# Allow duplice manifest entries when not file list is given because the +# FreeBSD METALOG still includes it. +DUPFLAG=-D +EXTRAS= +FILELIST= +GROUP= +KEYDIR= +KEYUSERS= +PASSWD= + +while getopts "Bde:f:g:K:k:p:s:" opt; do + case "$opt" in + B) BFLAG="-B ${OPTARG}" ;; + d) DEBUG=1 ;; + e) EXTRAS="${EXTRAS} ${OPTARG}" ;; + f) FILELIST="${OPTARG}"; DUPFLAG= ;; + g) GROUP="${OPTARG}" ;; + K) KEYUSERS="${KEYUSERS} ${OPTARG}" ;; + k) KEYDIR="${OPTARG}" ;; + p) PASSWD="${OPTARG}" ;; + s) SIZE="${OPTARG}" ;; + *) usage ;; + esac +done +shift $(($OPTIND - 1)) + +if [ $# -ne 2 ]; then + usage; +fi + +IMGFILE=$(realpath $(dirname $1))/$(basename $1) +BSDROOT=$2 + +DBDIR=${BSDROOT}/etc + +if [ ! -r ${BSDROOT}/METALOG ]; then + err 1 "${BSDROOT} does not contain a METALOG" +fi + +if [ -n "${GROUP}" -a -z "${PASSWD}" ]; then + warn "-g requires -p" + usage +fi + +if [ -n "${KEYUSERS}" -a -z "${KEYDIR}" ]; then + warn "-K requires -k" + usage +fi +if [ -n "${KEYDIR}" -a -z "${KEYUSERS}" ]; then + KEYUSERS=root +fi + +tmpdir=`mktemp -d /tmp/makeroot.XXXXX` +if [ -z "${tmpdir}" -o ! -d "${tmpdir}" ]; then + err 1 "failed to create tmpdir" +fi +trap atexit EXIT + +manifest=${tmpdir}/manifest + +echo "#mtree 2.0" > ${manifest} + +if [ -n "${PASSWD}" ]; then + cp ${PASSWD} ${tmpdir}/master.passwd + pwd_mkdb -d ${tmpdir} -p ${tmpdir}/master.passwd + if [ -z "${GROUP}" ]; then + cp ${DBDIR}/group ${tmpdir} + else + cp ${GROUP} ${tmpdir} + fi + + cat <<EOF >> ${tmpdir}/passwd.mtree +./etc/group type=file uname=root gname=wheel mode=0644 contents=${tmpdir}/group +./etc/master.passwd type=file uname=root gname=wheel mode=0600 contents=${tmpdir}/master.passwd +./etc/passwd type=file mode=0644 uname=root gname=wheel contents=${tmpdir}/passwd +./etc/pwd.db type=file mode=0644 uname=root gname=wheel contents=${tmpdir}/pwd.db +./etc/spwd.db type=file mode=0600 uname=root gname=wheel contents=${tmpdir}/spwd.db +EOF + EXTRAS="${EXTRAS} ${tmpdir}/passwd.mtree" + + DBDIR=${tmpdir} +fi + +if [ -n "${FILELIST}" ]; then + # build manifest from root manifest and FILELIST + (echo .; grep -v ^# ${FILELIST} | while read path; do + # Print each included path and all its sub-paths with a ./ + # prepended. The "sort -u" will then discard all the + # duplicate directory entries. This ensures that we + # extract the permissions for each unlisted directory + # from the METALOG. + path="/${path}" + while [ -n "${path}" ]; do + echo ".${path}" + path="${path%/*}" + done + done) | sort -u ${BSDROOT}/METALOG - | \ + awk ' + !/ type=/ { file = $1 } + / type=/ { if ($1 == file) {print} }' >> ${manifest} +else + # Start with all the files in BSDROOT/METALOG except those in + # one of the EXTRAS manifests. + grep -h type=file ${EXTRAS} | cut -d' ' -f1 | \ + sort -u ${BSDROOT}/METALOG - | awk ' + !/ type=/ { file = $1 } + / type=/ { if ($1 != file) {print} }' >> ${manifest} +fi + +# For each extras file, add contents kyes relative to the directory the +# manifest lives in for each file line that does not have one. Adjust +# contents keys relative to ./ to be relative to the same directory. +for eman in ${EXTRAS}; do + if [ ! -f ${eman} ]; then + err 1 "${eman} is not a regular file" + fi + extradir=`realpath ${eman}`; extradir=`dirname ${extradir}` + + awk '{ + if ($0 !~ /type=file/) { + print + } else { + if ($0 !~ /contents=/) { + printf ("%s contents=%s\n", $0, $1) + } else { + print + } + } + }' ${eman} | \ + sed -e "s|contents=\./|contents=${extradir}/|" >> ${manifest} +done + +# /etc/rcorder.start allows the startup order to be stable even if +# not all startup scripts are installed. In theory it should be +# unnecessicary, but dependencies in rc.d appear to be under recorded. +# This is a hack local to beri/cheribsd. +# +echo /etc/rc.d/FIRST > ${tmpdir}/rcorder.start +rcorder -s nostart ${BSDROOT}/etc/rc.d/* | sed -e "s:^${BSDROOT}::" | \ + grep -v LAST | grep -v FIRST >> \ + ${tmpdir}/rcorder.start +echo /etc/rc.d/LAST >> ${tmpdir}/rcorder.start +echo "./etc/rcorder.start type=file mode=644 uname=root gname=wheel" \ + "contents=${tmpdir}/rcorder.start" >> ${manifest} + +# Add all public keys in KEYDIR to roots' authorized_keys file. +if [ -n "${KEYDIR}" ]; then + cat ${KEYDIR}/*.pub > ${tmpdir}/authorized_keys + if [ ! -s ${tmpdir}/authorized_keys ]; then + err 1 "no keys found in ${KEYDIR}" + fi + for user in ${KEYUSERS}; do + userdir=`awk -F: "{if (\\\$1 == \"${user}\") {print \\\$9; exit} }" ${DBDIR}/master.passwd` + gid=`awk -F: "{if (\\\$1 == \"${user}\") {print \\\$4; exit} }" ${DBDIR}/master.passwd` + group=`awk -F: "{if (\\\$3 == \"${gid}\") {print \\\$1; exit} }" ${DBDIR}/group` + if [ -z "${userdir}" ]; then + err 1 "${user}: not found in ${DBDIR}/master.passwd" + fi + echo ".${userdir}/.ssh type=dir mode=700 uname=${user} gname=${group}" >> ${manifest} + echo ".${userdir}/.ssh/authorized_keys type=file mode=600 uname=${user} gname=${group} contents=${tmpdir}/authorized_keys" >> ${manifest} + done +fi + +if [ -n "${SIZE}" ]; then +SIZEFLAG="-s ${SIZE}" +fi + +cd ${BSDROOT}; makefs ${DUPFLAG} -N ${DBDIR} ${SIZEFLAG} ${BFLAG} \ + -t ffs -f 256 ${IMGFILE} ${manifest} diff --git a/tools/tools/nanobsd/gateworks/common b/tools/tools/nanobsd/gateworks/common index c23a2bf..182bfbd 100644 --- a/tools/tools/nanobsd/gateworks/common +++ b/tools/tools/nanobsd/gateworks/common @@ -113,7 +113,6 @@ WITHOUT_BSNMP=true WITHOUT_CALENDAR=true WITHOUT_CDDL=true WITHOUT_CTM=true -WITHOUT_CVS=true WITHOUT_DICT=true WITHOUT_EXAMPLES=true WITHOUT_FLOPPY=true diff --git a/tools/tools/nanobsd/nanobsd.sh b/tools/tools/nanobsd/nanobsd.sh index c3e96b3..216c900 100644 --- a/tools/tools/nanobsd/nanobsd.sh +++ b/tools/tools/nanobsd/nanobsd.sh @@ -359,8 +359,7 @@ setup_nanobsd ( ) ( echo "mount -o ro /dev/${NANO_DRIVE}s3" > conf/default/etc/remount # Put /tmp on the /var ramdisk (could be symlink already) - rmdir tmp || true - rm tmp || true + test -d tmp && rmdir tmp || rm -f tmp ln -s var/tmp tmp ) > ${NANO_OBJ}/_.dl 2>&1 @@ -413,12 +412,13 @@ populate_slice ( ) ( dir=$2 mnt=$3 lbl=$4 - test -z $2 && dir=${NANO_WORLDDIR}/var/empty - test -d $dir || dir=${NANO_WORLDDIR}/var/empty - echo "Creating ${dev} with ${dir} (mounting on ${mnt})" - newfs_part $dev $mnt $lbl - cd ${dir} - find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${mnt} + echo "Creating ${dev} (mounting on ${mnt})" + newfs_part ${dev} ${mnt} ${lbl} + if [ -n "${dir}" -a -d "${dir}" ]; then + echo "Populating ${lbl} from ${dir}" + cd ${dir} + find . -print | grep -Ev '/(CVS|\.svn)' | cpio -dumpv ${mnt} + fi df -i ${mnt} umount ${mnt} ) @@ -540,7 +540,7 @@ create_i386_diskimage ( ) ( if [ $NANO_IMAGES -gt 1 -a $NANO_INIT_IMG2 -gt 0 ] ; then # Duplicate to second image (if present) echo "Duplicating to second image..." - dd if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k + dd conv=sparse if=/dev/${MD}s1 of=/dev/${MD}s2 bs=64k mount /dev/${MD}s2a ${MNT} for f in ${MNT}/etc/fstab ${MNT}/conf/base/etc/fstab do @@ -564,12 +564,12 @@ create_i386_diskimage ( ) ( if [ "${NANO_MD_BACKING}" = "swap" ] ; then echo "Writing out ${NANO_IMGNAME}..." - dd if=/dev/${MD} of=${IMG} bs=64k + dd conv=sparse if=/dev/${MD} of=${IMG} bs=64k fi if ${do_copyout_partition} ; then echo "Writing out _.disk.image..." - dd if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k + dd conv=sparse if=/dev/${MD}s1 of=${NANO_DISKIMGDIR}/_.disk.image bs=64k fi mdconfig -d -u $MD @@ -588,6 +588,7 @@ last_orders () ( # after the build completed, for instance to copy the finished # image to a more convenient place: # cp ${NANO_DISKIMGDIR}/_.disk.image /home/ftp/pub/nanobsd.disk + true ) ####################################################################### diff --git a/tools/tools/netmap/Makefile b/tools/tools/netmap/Makefile index 2593a27..d737bac 100644 --- a/tools/tools/netmap/Makefile +++ b/tools/tools/netmap/Makefile @@ -3,7 +3,7 @@ # # For multiple programs using a single source file each, # we can just define 'progs' and create custom targets. -PROGS = pkt-gen bridge testpcap libnetmap.so +PROGS = pkt-gen bridge vale-ctl testpcap libnetmap.so CLEANFILES = $(PROGS) pcap.o nm_util.o NO_MAN= diff --git a/tools/tools/netmap/README b/tools/tools/netmap/README index 3520790..2bde6f2 100644 --- a/tools/tools/netmap/README +++ b/tools/tools/netmap/README @@ -21,3 +21,4 @@ BSD netmap 0.77 3.82 ports/trafshow (version 5) 0.94 7.7 net-mgmt/ipcad (ip accounting daemon) 0.9 5.0 net-mgmt/darkstat (ip accounting + graphing) + 0.83 2.45 net-mgmt/iftop (curses traffic display) diff --git a/tools/tools/netmap/bridge.c b/tools/tools/netmap/bridge.c index 473ee0c..0aca44d 100644 --- a/tools/tools/netmap/bridge.c +++ b/tools/tools/netmap/bridge.c @@ -14,7 +14,7 @@ int verbose = 0; -char *version = "$Id: bridge.c 12016 2013-01-23 17:24:22Z luigi $"; +char *version = "$Id$"; static int do_abort = 0; @@ -50,7 +50,12 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring, while (limit-- > 0) { struct netmap_slot *rs = &rxring->slot[j]; struct netmap_slot *ts = &txring->slot[k]; +#ifdef NO_SWAP + char *rxbuf = NETMAP_BUF(rxring, rs->buf_idx); + char *txbuf = NETMAP_BUF(txring, ts->buf_idx); +#else uint32_t pkt; +#endif /* swap packets */ if (ts->buf_idx < 2 || rs->buf_idx < 2) { @@ -58,20 +63,24 @@ process_rings(struct netmap_ring *rxring, struct netmap_ring *txring, j, rs->buf_idx, k, ts->buf_idx); sleep(2); } +#ifndef NO_SWAP pkt = ts->buf_idx; ts->buf_idx = rs->buf_idx; rs->buf_idx = pkt; - +#endif /* copy the packet length. */ if (rs->len < 14 || rs->len > 2048) D("wrong len %d rx[%d] -> tx[%d]", rs->len, j, k); else if (verbose > 1) D("%s send len %d rx[%d] -> tx[%d]", msg, rs->len, j, k); ts->len = rs->len; - +#ifdef NO_SWAP + pkt_copy(rxbuf, txbuf, ts->len); +#else /* report the buffer change. */ ts->flags |= NS_BUF_CHANGED; rs->flags |= NS_BUF_CHANGED; +#endif /* NO_SWAP */ j = NETMAP_RING_NEXT(rxring, j); k = NETMAP_RING_NEXT(txring, k); } diff --git a/tools/tools/netmap/nm_util.c b/tools/tools/netmap/nm_util.c index 2b2c0ca..6153603 100644 --- a/tools/tools/netmap/nm_util.c +++ b/tools/tools/netmap/nm_util.c @@ -221,7 +221,6 @@ netmap_close(struct my_ring *me) D(""); if (me->mem) munmap(me->mem, me->memsize); - ioctl(me->fd, NIOCUNREGIF, NULL); close(me->fd); return (0); } diff --git a/tools/tools/netmap/pcap.c b/tools/tools/netmap/pcap.c index c2acd1a..f30f57b 100644 --- a/tools/tools/netmap/pcap.c +++ b/tools/tools/netmap/pcap.c @@ -13,7 +13,7 @@ #define MY_PCAP #include "nm_util.h" -char *version = "$Id: pcap.c 11463 2012-07-30 15:26:02Z luigi $"; +char *version = "$Id$"; int verbose = 0; /* @@ -445,7 +445,6 @@ pcap_close(pcap_t *p) if (me->mem) munmap(me->mem, me->memsize); /* restore original flags ? */ - ioctl(me->fd, NIOCUNREGIF, NULL); close(me->fd); bzero(me, sizeof(*me)); free(me); diff --git a/tools/tools/netmap/pkt-gen.c b/tools/tools/netmap/pkt-gen.c index 7c2ad98..901175e 100644 --- a/tools/tools/netmap/pkt-gen.c +++ b/tools/tools/netmap/pkt-gen.c @@ -25,7 +25,7 @@ /* * $FreeBSD$ - * $Id: pkt-gen.c 12024 2013-01-25 05:41:51Z luigi $ + * $Id$ * * Example program to show how to build a multithreaded packet * source/sink using the netmap device. @@ -38,6 +38,8 @@ #include "nm_util.h" +#include <ctype.h> // isprint() + const char *default_payload="netmap pkt-gen payload\n" "http://info.iet.unipi.it/~luigi/netmap/ "; @@ -86,9 +88,14 @@ struct glob_arg { #define OPT_COPY 4 #define OPT_MEMCPY 8 #define OPT_TS 16 /* add a timestamp */ +#define OPT_INDIRECT 32 /* use indirect buffers, tx only */ +#define OPT_DUMP 64 /* dump rx/tx traffic */ int dev_type; pcap_t *p; + int tx_rate; + struct timespec tx_period; + int affinity; int main_fd; int report_interval; @@ -114,7 +121,7 @@ struct targ { struct netmap_if *nifp; uint16_t qfirst, qlast; /* range of queues to scan */ volatile uint64_t count; - struct timeval tic, toc; + struct timespec tic, toc; int me; pthread_t thread; int affinity; @@ -343,6 +350,33 @@ wrapsum(u_int32_t sum) return (htons(sum)); } +/* Check the payload of the packet for errors (use it for debug). + * Look for consecutive ascii representations of the size of the packet. + */ +static void +dump_payload(char *p, int len, struct netmap_ring *ring, int cur) +{ + char buf[128]; + int i, j, i0; + + /* get the length in ASCII of the length of the packet. */ + + printf("ring %p cur %5d len %5d buf %p\n", ring, cur, len, p); + /* hexdump routine */ + for (i = 0; i < len; ) { + memset(buf, sizeof(buf), ' '); + sprintf(buf, "%5d: ", i); + i0 = i; + for (j=0; j < 16 && i < len; i++, j++) + sprintf(buf+7+j*3, "%02x ", (uint8_t)(p[i])); + i = i0; + for (j=0; j < 16 && i < len; i++, j++) + sprintf(buf+7+j + 48, "%c", + isprint(p[i]) ? p[i] : '.'); + printf("%s\n", buf); + } +} + /* * Fill a packet with some payload. * We create a UDP packet so the payload starts at @@ -354,6 +388,7 @@ wrapsum(u_int32_t sum) #define uh_ulen len #define uh_sum check #endif /* linux */ + static void initialize_packet(struct targ *targ) { @@ -362,11 +397,13 @@ initialize_packet(struct targ *targ) struct ip *ip; struct udphdr *udp; uint16_t paylen = targ->g->pkt_size - sizeof(*eh) - sizeof(struct ip); - int i, l, l0 = strlen(default_payload); + const char *payload = targ->g->options & OPT_INDIRECT ? + "XXXXXXXXXXXXXXXXXXXXXX" : default_payload; + int i, l, l0 = strlen(payload); for (i = 0; i < paylen;) { l = min(l0, paylen - i); - bcopy(default_payload, pkt->body + i, l); + bcopy(payload, pkt->body + i, l); i += l; } pkt->body[i-1] = '\0'; @@ -412,34 +449,9 @@ initialize_packet(struct targ *targ) bcopy(&targ->g->src_mac.start, eh->ether_shost, 6); bcopy(&targ->g->dst_mac.start, eh->ether_dhost, 6); eh->ether_type = htons(ETHERTYPE_IP); + // dump_payload((void *)pkt, targ->g->pkt_size, NULL, 0); } -/* Check the payload of the packet for errors (use it for debug). - * Look for consecutive ascii representations of the size of the packet. - */ -static void -check_payload(char *p, int psize) -{ - char temp[64]; - int n_read, size, sizelen; - - /* get the length in ASCII of the length of the packet. */ - sizelen = sprintf(temp, "%d", psize) + 1; // include a whitespace - - /* dummy payload. */ - p += 14; /* skip packet header. */ - n_read = 14; - while (psize - n_read >= sizelen) { - sscanf(p, "%d", &size); - if (size != psize) { - D("Read %d instead of %d", size, psize); - break; - } - - p += sizelen; - n_read += sizelen; - } -} /* @@ -472,7 +484,13 @@ send_packets(struct netmap_ring *ring, struct pkt *pkt, struct netmap_slot *slot = &ring->slot[cur]; char *p = NETMAP_BUF(ring, slot->buf_idx); - if (options & OPT_COPY) + slot->flags = 0; + if (options & OPT_DUMP) + dump_payload(p, size, ring, cur); + if (options & OPT_INDIRECT) { + slot->flags |= NS_INDIRECT; + *((struct pkt **)(void *)p) = pkt; + } else if (options & OPT_COPY) pkt_copy(pkt, p, size); else if (options & OPT_MEMCPY) memcpy(p, pkt, size); @@ -669,6 +687,76 @@ ponger_body(void *data) return NULL; } +static __inline int +timespec_ge(const struct timespec *a, const struct timespec *b) +{ + + if (a->tv_sec > b->tv_sec) + return (1); + if (a->tv_sec < b->tv_sec) + return (0); + if (a->tv_nsec >= b->tv_nsec) + return (1); + return (0); +} + +static __inline struct timespec +timeval2spec(const struct timeval *a) +{ + struct timespec ts = { + .tv_sec = a->tv_sec, + .tv_nsec = a->tv_usec * 1000 + }; + return ts; +} + +static __inline struct timeval +timespec2val(const struct timespec *a) +{ + struct timeval tv = { + .tv_sec = a->tv_sec, + .tv_usec = a->tv_nsec / 1000 + }; + return tv; +} + + +static int +wait_time(struct timespec ts, struct timespec *wakeup_ts, long long *waited) +{ + struct timespec curtime; + + curtime.tv_sec = 0; + curtime.tv_nsec = 0; + + if (clock_gettime(CLOCK_REALTIME_PRECISE, &curtime) == -1) { + D("clock_gettime: %s", strerror(errno)); + return (-1); + } + while (timespec_ge(&ts, &curtime)) { + if (waited != NULL) + (*waited)++; + if (clock_gettime(CLOCK_REALTIME_PRECISE, &curtime) == -1) { + D("clock_gettime"); + return (-1); + } + } + if (wakeup_ts != NULL) + *wakeup_ts = curtime; + return (0); +} + +static __inline void +timespec_add(struct timespec *tsa, struct timespec *tsb) +{ + tsa->tv_sec += tsb->tv_sec; + tsa->tv_nsec += tsb->tv_nsec; + if (tsa->tv_nsec >= 1000000000) { + tsa->tv_sec++; + tsa->tv_nsec -= 1000000000; + } +} + static void * sender_body(void *data) @@ -680,7 +768,11 @@ sender_body(void *data) struct netmap_ring *txring; int i, n = targ->g->npackets / targ->g->nthreads, sent = 0; int options = targ->g->options | OPT_COPY; -D("start"); + struct timespec tmptime, nexttime = { 0, 0}; // XXX silence compiler + int rate_limit = targ->g->tx_rate; + long long waited = 0; + + D("start"); if (setaffinity(targ->thread, targ->affinity)) goto quit; /* setup poll(2) mechanism. */ @@ -689,8 +781,18 @@ D("start"); fds[0].events = (POLLOUT); /* main loop.*/ - gettimeofday(&targ->tic, NULL); - + clock_gettime(CLOCK_REALTIME_PRECISE, &targ->tic); + if (rate_limit) { + tmptime.tv_sec = 2; + tmptime.tv_nsec = 0; + timespec_add(&targ->tic, &tmptime); + targ->tic.tv_nsec = 0; + if (wait_time(targ->tic, NULL, NULL) == -1) { + D("wait_time: %s", strerror(errno)); + goto quit; + } + nexttime = targ->tic; + } if (targ->g->dev_type == DEV_PCAP) { int size = targ->g->pkt_size; void *pkt = &targ->pkt; @@ -718,8 +820,18 @@ D("start"); } } } else { + int tosend = 0; while (!targ->cancel && (n == 0 || sent < n)) { + if (rate_limit && tosend <= 0) { + tosend = targ->g->burst; + timespec_add(&nexttime, &targ->g->tx_period); + if (wait_time(nexttime, &tmptime, &waited) == -1) { + D("wait_time"); + goto quit; + } + } + /* * wait for available room in the send queue(s) */ @@ -737,7 +849,7 @@ D("start"); options &= ~OPT_COPY; } for (i = targ->qfirst; i < targ->qlast; i++) { - int m, limit = targ->g->burst; + int m, limit = rate_limit ? tosend : targ->g->burst; if (n > 0 && n - sent < limit) limit = n - sent; txring = NETMAP_TXRING(nifp, i); @@ -746,6 +858,7 @@ D("start"); m = send_packets(txring, &targ->pkt, targ->g->pkt_size, limit, options); sent += m; + tosend -= m; targ->count = sent; } } @@ -762,7 +875,7 @@ D("start"); } } - gettimeofday(&targ->toc, NULL); + clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc); targ->completed = 1; targ->count = sent; @@ -785,7 +898,7 @@ receive_pcap(u_char *user, const struct pcap_pkthdr * h, } static int -receive_packets(struct netmap_ring *ring, u_int limit, int skip_payload) +receive_packets(struct netmap_ring *ring, u_int limit, int dump) { u_int cur, rx; @@ -796,8 +909,9 @@ receive_packets(struct netmap_ring *ring, u_int limit, int skip_payload) struct netmap_slot *slot = &ring->slot[cur]; char *p = NETMAP_BUF(ring, slot->buf_idx); - if (!skip_payload) - check_payload(p, slot->len); + slot->flags = OPT_INDIRECT; // XXX + if (dump) + dump_payload(p, slot->len, ring, cur); cur = NETMAP_RING_NEXT(ring, cur); } @@ -834,7 +948,7 @@ receiver_body(void *data) } /* main loop, exit after 1s silence */ - gettimeofday(&targ->tic, NULL); + clock_gettime(CLOCK_REALTIME_PRECISE, &targ->tic); if (targ->g->dev_type == DEV_PCAP) { while (!targ->cancel) { /* XXX should we poll ? */ @@ -849,11 +963,12 @@ receiver_body(void *data) targ->count++; } } else { + int dump = targ->g->options & OPT_DUMP; while (!targ->cancel) { /* Once we started to receive packets, wait at most 1 seconds before quitting. */ - if (poll(fds, 1, 1 * 1000) <= 0 && targ->g->forever == 0) { - gettimeofday(&targ->toc, NULL); + if (poll(fds, 1, 1 * 1000) <= 0 && !targ->g->forever) { + clock_gettime(CLOCK_REALTIME_PRECISE, &targ->toc); targ->toc.tv_sec -= 1; /* Subtract timeout time. */ break; } @@ -865,8 +980,7 @@ receiver_body(void *data) if (rxring->avail == 0) continue; - m = receive_packets(rxring, targ->g->burst, - SKIP_PAYLOAD); + m = receive_packets(rxring, targ->g->burst, dump); received += m; } targ->count = received; @@ -1085,11 +1199,13 @@ main_thread(struct glob_arg *g) timerclear(&tic); timerclear(&toc); for (i = 0; i < g->nthreads; i++) { + struct timespec t_tic, t_toc; /* * Join active threads, unregister interfaces and close * file descriptors. */ - pthread_join(targs[i].thread, NULL); + if (targs[i].used) + pthread_join(targs[i].thread, NULL); close(targs[i].fd); if (targs[i].completed == 0) @@ -1100,10 +1216,12 @@ main_thread(struct glob_arg *g) * how long it took to send all the packets. */ count += targs[i].count; - if (!timerisset(&tic) || timercmp(&targs[i].tic, &tic, <)) - tic = targs[i].tic; - if (!timerisset(&toc) || timercmp(&targs[i].toc, &toc, >)) - toc = targs[i].toc; + t_tic = timeval2spec(&tic); + t_toc = timeval2spec(&toc); + if (!timerisset(&tic) || timespec_ge(&targs[i].tic, &t_tic)) + tic = timespec2val(&targs[i].tic); + if (!timerisset(&toc) || timespec_ge(&targs[i].toc, &t_toc)) + toc = timespec2val(&targs[i].toc); } /* print output. */ @@ -1115,7 +1233,6 @@ main_thread(struct glob_arg *g) rx_output(count, delta_t); if (g->dev_type == DEV_NETMAP) { - ioctl(g->main_fd, NIOCUNREGIF, NULL); // XXX deprecated munmap(g->mmap_addr, g->mmap_size); close(g->main_fd); } @@ -1224,9 +1341,11 @@ main(int arc, char **argv) g.burst = 512; // default g.nthreads = 1; g.cpus = 1; + g.forever = 1; + g.tx_rate = 0; while ( (ch = getopt(arc, argv, - "a:f:n:i:t:r:l:d:s:D:S:b:c:o:p:PT:w:Wv")) != -1) { + "a:f:n:i:It:r:l:d:s:D:S:b:c:o:p:PT:w:WvR:X")) != -1) { struct sf *fn; switch(ch) { @@ -1266,6 +1385,10 @@ main(int arc, char **argv) g.dev_type = DEV_NETMAP; break; + case 'I': + g.options |= OPT_INDIRECT; /* XXX use indirect buffer */ + break; + case 't': /* send, deprecated */ D("-t deprecated, please use -f tx -n %s", optarg); g.td_body = sender_body; @@ -1298,8 +1421,8 @@ main(int arc, char **argv) wait_link = atoi(optarg); break; - case 'W': - g.forever = 1; /* do not exit rx even with no traffic */ + case 'W': /* XXX changed default */ + g.forever = 0; /* do not exit rx even with no traffic */ break; case 'b': /* burst */ @@ -1325,6 +1448,12 @@ main(int arc, char **argv) break; case 'v': verbose++; + break; + case 'R': + g.tx_rate = atoi(optarg); + break; + case 'X': + g.options |= OPT_DUMP; } } @@ -1467,12 +1596,30 @@ main(int arc, char **argv) } if (g.options) { - D("special options:%s%s%s%s\n", + D("--- SPECIAL OPTIONS:%s%s%s%s%s\n", g.options & OPT_PREFETCH ? " prefetch" : "", g.options & OPT_ACCESS ? " access" : "", g.options & OPT_MEMCPY ? " memcpy" : "", + g.options & OPT_INDIRECT ? " indirect" : "", g.options & OPT_COPY ? " copy" : ""); } + + if (g.tx_rate == 0) { + g.tx_period.tv_sec = 0; + g.tx_period.tv_nsec = 0; + } else if (g.tx_rate == 1) { + g.tx_period.tv_sec = 1; + g.tx_period.tv_nsec = 0; + } else { + g.tx_period.tv_sec = 0; + g.tx_period.tv_nsec = (1e9 / g.tx_rate) * g.burst; + if (g.tx_period.tv_nsec > 1000000000) { + g.tx_period.tv_sec = g.tx_period.tv_nsec / 1000000000; + g.tx_period.tv_nsec = g.tx_period.tv_nsec % 1000000000; + } + } + D("Sending %d packets every %d.%09d ns", + g.burst, (int)g.tx_period.tv_sec, (int)g.tx_period.tv_nsec); /* Wait for PHY reset. */ D("Wait %d secs for phy reset", wait_link); sleep(wait_link); diff --git a/tools/tools/netmap/vale-ctl.c b/tools/tools/netmap/vale-ctl.c new file mode 100644 index 0000000..0a478ba --- /dev/null +++ b/tools/tools/netmap/vale-ctl.c @@ -0,0 +1,163 @@ +/* + * Copyright (C) 2013 Michio Honda. 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$ */ + +#include <errno.h> +#include <stdio.h> +#include <inttypes.h> /* PRI* macros */ +#include <string.h> /* strcmp */ +#include <fcntl.h> /* open */ +#include <unistd.h> /* close */ +#include <sys/ioctl.h> /* ioctl */ +#include <sys/param.h> +#include <net/if.h> /* ifreq */ +#include <net/netmap.h> +#include <net/netmap_user.h> +#include <libgen.h> /* basename */ + +/* debug support */ +#define ND(format, ...) do {} while(0) +#define D(format, ...) \ + fprintf(stderr, "%s [%d] " format "\n", \ + __FUNCTION__, __LINE__, ##__VA_ARGS__) + +static int +bdg_ctl(const char *name, int nr_cmd, int nr_arg) +{ + struct nmreq nmr; + int error = 0; + int fd = open("/dev/netmap", O_RDWR); + + if (fd == -1) { + D("Unable to open /dev/netmap"); + return -1; + } + + bzero(&nmr, sizeof(nmr)); + nmr.nr_version = NETMAP_API; + if (name != NULL) /* might be NULL */ + strncpy(nmr.nr_name, name, sizeof(nmr.nr_name)); + nmr.nr_cmd = nr_cmd; + + switch (nr_cmd) { + case NETMAP_BDG_ATTACH: + case NETMAP_BDG_DETACH: + if (nr_arg && nr_arg != NETMAP_BDG_HOST) + nr_arg = 0; + nmr.nr_arg1 = nr_arg; + error = ioctl(fd, NIOCREGIF, &nmr); + if (error == -1) + D("Unable to %s %s to the bridge", nr_cmd == + NETMAP_BDG_DETACH?"detach":"attach", name); + else + D("Success to %s %s to the bridge\n", nr_cmd == + NETMAP_BDG_DETACH?"detach":"attach", name); + break; + + case NETMAP_BDG_LIST: + if (strlen(nmr.nr_name)) { /* name to bridge/port info */ + error = ioctl(fd, NIOCGINFO, &nmr); + if (error) + D("Unable to obtain info for %s", name); + else + D("%s at bridge:%d port:%d", name, nmr.nr_arg1, + nmr.nr_arg2); + break; + } + + /* scan all the bridges and ports */ + nmr.nr_arg1 = nmr.nr_arg2 = 0; + for (; !ioctl(fd, NIOCGINFO, &nmr); nmr.nr_arg2++) { + D("bridge:%d port:%d %s", nmr.nr_arg1, nmr.nr_arg2, + nmr.nr_name); + nmr.nr_name[0] = '\0'; + } + + break; + + default: /* GINFO */ + nmr.nr_cmd = nmr.nr_arg1 = nmr.nr_arg2 = 0; + error = ioctl(fd, NIOCGINFO, &nmr); + if (error) + D("Unable to get if info for %s", name); + else + D("%s: %d queues.", name, nmr.nr_rx_rings); + break; + } + close(fd); + return error; +} + +int +main(int argc, char *argv[]) +{ + int ch, nr_cmd = 0, nr_arg = 0; + const char *command = basename(argv[0]); + char *name = NULL; + + if (argc != 3 && argc != 1 /* list all */ ) { +usage: + fprintf(stderr, + "Usage:\n" + "%s arguments\n" + "\t-g interface interface name to get info\n" + "\t-d interface interface name to be detached\n" + "\t-a interface interface name to be attached\n" + "\t-h interface interface name to be attached with the host stack\n" + "\t-l list all or specified bridge's interfaces\n" + "", command); + return 0; + } + + while ((ch = getopt(argc, argv, "d:a:h:g:l:")) != -1) { + switch (ch) { + default: + fprintf(stderr, "bad option %c %s", ch, optarg); + goto usage; + case 'd': + nr_cmd = NETMAP_BDG_DETACH; + break; + case 'a': + nr_cmd = NETMAP_BDG_ATTACH; + break; + case 'h': + nr_cmd = NETMAP_BDG_ATTACH; + nr_arg = NETMAP_BDG_HOST; + break; + case 'g': + nr_cmd = 0; + break; + case 'l': + nr_cmd = NETMAP_BDG_LIST; + break; + } + name = optarg; + } + if (argc == 1) + nr_cmd = NETMAP_BDG_LIST; + bdg_ctl(name, nr_cmd, nr_arg); + return 0; +} diff --git a/tools/tools/notescheck/notescheck.py b/tools/tools/notescheck/notescheck.py index 35915b9..8e23387 100644 --- a/tools/tools/notescheck/notescheck.py +++ b/tools/tools/notescheck/notescheck.py @@ -93,7 +93,7 @@ class Option: return if global_platform in self.defines: - # If the device is defined globally ans is never tested, whine. + # If the device is defined globally and is never tested, whine. if len(self.tests) == 0: print('WARN: %s is defined globally but never tested' % \ (self.title())) diff --git a/tools/tools/pciroms/pciroms.c b/tools/tools/pciroms/pciroms.c index 460c7ef..9919c20 100644 --- a/tools/tools/pciroms/pciroms.c +++ b/tools/tools/pciroms/pciroms.c @@ -10,25 +10,18 @@ * 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. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by Bruce M. Simpson. - * 4. Neither the name of Bruce M. Simpson nor the names of - * contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY BRUCE M. SIMPSON AND AFFILIATES - * ``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 FOUNDATION 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. * + * 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 <sys/cdefs.h> diff --git a/tools/tools/sysbuild/sysbuild.sh b/tools/tools/sysbuild/sysbuild.sh index 2f91e86..0b39fe2 100644 --- a/tools/tools/sysbuild/sysbuild.sh +++ b/tools/tools/sysbuild/sysbuild.sh @@ -91,7 +91,7 @@ SERCONS=false PORTS_WE_WANT=' ' -PORTS_OPTS="BATCH=YES MAKE_IDEA=YES A4=yes" +PORTS_OPTS="BATCH=YES A4=yes" CONFIGFILES=' ' diff --git a/tools/tools/sysdoc/sysdoc.sh b/tools/tools/sysdoc/sysdoc.sh index c428174..b07c53d 100644 --- a/tools/tools/sysdoc/sysdoc.sh +++ b/tools/tools/sysdoc/sysdoc.sh @@ -88,7 +88,7 @@ EOF # tunables in our tunables.mdoc file and generate # the final 'inner circle' of our manual page. markup_create() { - sort < _names | \ + sort -u < _names | \ xargs -n 1 /bin/sh ./sysctl.sh \ > markup.file \ 2> tunables.TODO @@ -238,9 +238,13 @@ if [ -z "$LOCATION" ] ; && for x in `find $LOCATION -name '*.kld'` \ $LOCATION/kernel; \ do nm $x | \ - grep ' sysctl___' | uniq | \ - sed 's/sysctl___//g' | sed 's/_/./g' | \ - awk {'print $3'} > _names; + sed -n '/sysctl___/ { + 's/[\.a-z_]*sysctl___//g' + 's/_/./g' + p + }' | \ + awk {'print $3'} | \ + sort -u > _names; done; markup_create page_create diff --git a/tools/tools/sysdoc/tunables.mdoc b/tools/tools/sysdoc/tunables.mdoc index 35ef9c0..505c4a7 100644 --- a/tools/tools/sysdoc/tunables.mdoc +++ b/tools/tools/sysdoc/tunables.mdoc @@ -1093,6 +1093,13 @@ line programs. kern.quantum --- +kern.random.adaptors +str + +Displays registered PRNG adaptors. +This is a read-only variable. + +--- kern.random.sys.burst --- @@ -2259,9 +2266,6 @@ Displays the number of swap devices available to the system. This is a read-only variable. --- -vm.pageout_algorithm - ---- vm.pageout_full_stats_interval --- diff --git a/tools/tools/umastat/umastat.c b/tools/tools/umastat/umastat.c index 3a43c37..758195e 100644 --- a/tools/tools/umastat/umastat.c +++ b/tools/tools/umastat/umastat.c @@ -79,7 +79,7 @@ kread(kvm_t *kvm, void *kvm_pointer, void *address, size_t size, } static int -kread_string(kvm_t *kvm, void *kvm_pointer, char *buffer, int buflen) +kread_string(kvm_t *kvm, const void *kvm_pointer, char *buffer, int buflen) { ssize_t ret; int i; @@ -151,7 +151,7 @@ uma_print_keg_flags(struct uma_keg *ukp, const char *spaces) if (ukp->uk_flags & flaginfo[i].fi_flag) { if (count++ > 0) printf(" | "); - printf(flaginfo[i].fi_name); + printf("%s", flaginfo[i].fi_name); } } diff --git a/tools/tools/usbtest/Makefile b/tools/tools/usbtest/Makefile new file mode 100644 index 0000000..1cc0c83 --- /dev/null +++ b/tools/tools/usbtest/Makefile @@ -0,0 +1,40 @@ +# +# $FreeBSD$ +# +# Copyright (c) 2013 Hans Petter Selasky. 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. +# +PROG= usbtest +MAN= +SRCS+= usbtest.c +SRCS+= usb_msc_test.c +SRCS+= usb_modem_test.c +SRCS+= usb_control_ep_test.c + +LDADD+= -lusb + +WARNS= 3 + +CFLAGS+= -I ${.CURDIR}/../../../sys/dev/usb/gadget + +.include <bsd.prog.mk> diff --git a/tools/tools/usbtest/usb_control_ep_test.c b/tools/tools/usbtest/usb_control_ep_test.c new file mode 100644 index 0000000..87c5fc1 --- /dev/null +++ b/tools/tools/usbtest/usb_control_ep_test.c @@ -0,0 +1,673 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2007-2010 Hans Petter Selasky. 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <err.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <libusb20.h> +#include <libusb20_desc.h> + +#include <dev/usb/usb_endian.h> +#include <dev/usb/usb.h> +#include <dev/usb/usb_cdc.h> + +#include "usbtest.h" + +static void +set_ctrl_ep_fail(int bus, int dev, int ds_fail, int ss_fail) +{ + int error; + + error = sysctlbyname("hw.usb.ctrl_bus_fail", NULL, NULL, + &bus, sizeof(bus)); + if (error != 0) + goto emissing; + + error = sysctlbyname("hw.usb.ctrl_dev_fail", NULL, NULL, + &dev, sizeof(dev)); + if (error != 0) + goto emissing; + + error = sysctlbyname("hw.usb.ctrl_ds_fail", NULL, NULL, + &ds_fail, sizeof(ds_fail)); + if (error != 0) + goto emissing; + + error = sysctlbyname("hw.usb.ctrl_ss_fail", NULL, NULL, + &ss_fail, sizeof(ss_fail)); + if (error != 0) + goto emissing; + return; + +emissing: + printf("Cannot set USB sysctl, missing USB_REQ_DEBUG option?\n"); +} + +void +usb_control_ep_error_test(uint16_t vid, uint16_t pid) +{ + struct LIBUSB20_CONTROL_SETUP_DECODED req; + struct libusb20_device *pdev; + uint8_t buffer[256]; + int error; + int fail = 0; + int bus; + int dev; + int cfg; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 0); + if (error) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + + bus = libusb20_dev_get_bus_number(pdev); + dev = libusb20_dev_get_address(pdev); + + for (cfg = 0; cfg != 255; cfg++) { + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &req); + req.bmRequestType = 0x80; /* read */ + req.bRequest = 0x06; /* descriptor */ + req.wValue = 0x0200 | cfg; /* config descriptor */ + req.wIndex = 0; + req.wLength = 255; + + printf("Test #%d.1/3 ...\n", cfg); + + set_ctrl_ep_fail(-1,-1,0,0); + + error = libusb20_dev_request_sync(pdev, &req, buffer, + NULL, 1000, 0); + if (error != 0) { + printf("Last configuration index is: %d\n", cfg - 1); + break; + } + + printf("Test #%d.2/3 ...\n", cfg); + + set_ctrl_ep_fail(bus,dev,1,1); + + error = libusb20_dev_request_sync(pdev, &req, buffer, + NULL, 1000, 0); + + set_ctrl_ep_fail(-1,-1,0,0); + + error = libusb20_dev_request_sync(pdev, &req, buffer, + NULL, 1000, 0); + if (error != 0) { + printf("Cannot fetch descriptor (unexpected)\n"); + fail++; + } + + printf("Test #%d.3/3 ...\n", cfg); + + set_ctrl_ep_fail(bus,dev,0,1); + + error = libusb20_dev_request_sync(pdev, &req, buffer, + NULL, 1000, 0); + + set_ctrl_ep_fail(-1,-1,0,0); + + error = libusb20_dev_request_sync(pdev, &req, buffer, + NULL, 1000, 0); + if (error != 0) { + printf("Cannot fetch descriptor (unexpected)\n"); + fail++; + } + } + + libusb20_dev_close(pdev); + libusb20_dev_free(pdev); + + printf("Test completed detecting %d failures\nDone\n\n", fail); +} + +void +usb_get_string_desc_test(uint16_t vid, uint16_t pid) +{ + struct libusb20_device *pdev; + uint32_t x; + uint32_t y; + uint32_t valid; + uint8_t *buf; + int error; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 0); + if (error) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + buf = malloc(256); + if (buf == NULL) { + printf("Cannot allocate memory\n"); + libusb20_dev_free(pdev); + return; + } + valid = 0; + + printf("Starting string descriptor test for " + "VID=0x%04x PID=0x%04x\n", vid, pid); + + for (x = 0; x != 256; x++) { + + if (libusb20_dev_check_connected(pdev) != 0) { + printf("Device disconnected\n"); + break; + } + printf("%d .. ", (int)x); + + fflush(stdout); + + error = libusb20_dev_req_string_simple_sync(pdev, x, buf, 255); + + if (error == 0) { + printf("\nINDEX=%d, STRING='%s' (Default language)\n", (int)x, buf); + fflush(stdout); + } else { + continue; + } + + valid = 0; + + for (y = 0; y != 65536; y++) { + + if (libusb20_dev_check_connected(pdev) != 0) { + printf("Device disconnected\n"); + break; + } + error = libusb20_dev_req_string_sync(pdev, x, y, buf, 256); + if (error == 0) + valid++; + } + + printf("String at INDEX=%d responds to %d " + "languages\n", (int)x, (int)valid); + } + + printf("\nDone\n"); + + free(buf); + + libusb20_dev_free(pdev); +} + +void +usb_port_reset_test(uint16_t vid, uint16_t pid, uint32_t duration) +{ + struct timeval sub_tv; + struct timeval ref_tv; + struct timeval res_tv; + + struct libusb20_device *pdev; + + int error; + int iter; + int errcnt; + + time_t last_sec; + + /* sysctl() - no set config */ + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 0); + if (error) { + libusb20_dev_free(pdev); + printf("Could not open USB device\n"); + return; + } + iter = 0; + + errcnt = 0; + + gettimeofday(&ref_tv, 0); + + last_sec = ref_tv.tv_sec; + + while (1) { + + gettimeofday(&sub_tv, 0); + + if (last_sec != sub_tv.tv_sec) { + + printf("STATUS: ID=%u, ERR=%u\n", + (int)iter, (int)errcnt); + + fflush(stdout); + + last_sec = sub_tv.tv_sec; + } + timersub(&sub_tv, &ref_tv, &res_tv); + + if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) + break; + + if (libusb20_dev_reset(pdev)) { + errcnt++; + usleep(50000); + } + if (libusb20_dev_check_connected(pdev) != 0) { + printf("Device disconnected\n"); + break; + } + iter++; + } + + libusb20_dev_reset(pdev); + + libusb20_dev_free(pdev); +} + +void +usb_set_config_test(uint16_t vid, uint16_t pid, uint32_t duration) +{ + struct libusb20_device *pdev; + struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; + int x; + int error; + int failed; + int exp; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 0); + if (error) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + failed = 0; + + printf("Starting set config test for " + "VID=0x%04x PID=0x%04x\n", vid, pid); + + for (x = 255; x > -1; x--) { + + error = libusb20_dev_set_config_index(pdev, x); + if (error == 0) { + if (x == 255) { + printf("Unconfiguring USB device " + "was successful\n"); + } else { + printf("Setting configuration %d " + "was successful\n", x); + } + } else { + failed++; + } + } + + ddesc = libusb20_dev_get_device_desc(pdev); + if (ddesc != NULL) + exp = ddesc->bNumConfigurations + 1; + else + exp = 1; + + printf("\n\n" + "Set configuration summary\n" + "Valid count: %d/%d %s\n" + "Failed count: %d\n", + 256 - failed, exp, + (exp == (256 - failed)) ? "(expected)" : "(unexpected)", + failed); + + libusb20_dev_free(pdev); +} + +void +usb_get_descriptor_test(uint16_t vid, uint16_t pid, uint32_t duration) +{ + struct libusb20_device *pdev; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + libusb20_dev_free(pdev); +} + +void +usb_suspend_resume_test(uint16_t vid, uint16_t pid, uint32_t duration) +{ + struct timeval sub_tv; + struct timeval ref_tv; + struct timeval res_tv; + + struct libusb20_device *pdev; + + time_t last_sec; + + int iter; + int error; + int ptimo; + int errcnt; + int power_old; + + ptimo = 1; /* second(s) */ + + error = sysctlbyname("hw.usb.power_timeout", NULL, NULL, + &ptimo, sizeof(ptimo)); + + if (error != 0) { + printf("WARNING: Could not set power " + "timeout to 1 (error=%d) \n", errno); + } + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 0); + if (error) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + power_old = libusb20_dev_get_power_mode(pdev); + + printf("Starting suspend and resume " + "test for VID=0x%04x PID=0x%04x\n", vid, pid); + + iter = 0; + errcnt = 0; + + gettimeofday(&ref_tv, 0); + + last_sec = ref_tv.tv_sec; + + while (1) { + + if (libusb20_dev_check_connected(pdev) != 0) { + printf("Device disconnected\n"); + break; + } + gettimeofday(&sub_tv, 0); + + if (last_sec != sub_tv.tv_sec) { + + printf("STATUS: ID=%u, ERR=%u\n", + (int)iter, (int)errcnt); + + fflush(stdout); + + last_sec = sub_tv.tv_sec; + } + timersub(&sub_tv, &ref_tv, &res_tv); + + if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) + break; + + error = libusb20_dev_set_power_mode(pdev, (iter & 1) ? + LIBUSB20_POWER_ON : LIBUSB20_POWER_SAVE); + + if (error) + errcnt++; + + /* wait before switching power mode */ + usleep(4100000 + + (((uint32_t)usb_ts_rand_noise()) % 2000000U)); + + iter++; + } + + /* restore default power mode */ + libusb20_dev_set_power_mode(pdev, power_old); + + libusb20_dev_free(pdev); +} + +void +usb_set_and_clear_stall_test(uint16_t vid, uint16_t pid) +{ + struct libusb20_device *pdev; + struct libusb20_transfer *pxfer; + + int iter; + int error; + int errcnt; + int ep; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + error = libusb20_dev_open(pdev, 1); + if (error) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + printf("Starting set and clear stall test " + "for VID=0x%04x PID=0x%04x\n", vid, pid); + + iter = 0; + errcnt = 0; + + for (ep = 2; ep != 32; ep++) { + + struct LIBUSB20_CONTROL_SETUP_DECODED setup_set_stall; + struct LIBUSB20_CONTROL_SETUP_DECODED setup_get_status; + + uint8_t epno = ((ep / 2) | ((ep & 1) << 7)); + uint8_t buf[1]; + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_set_stall); + setup_set_stall.bmRequestType = 0x02; /* write endpoint */ + setup_set_stall.bRequest = 0x03; /* set feature */ + setup_set_stall.wValue = 0x00; /* UF_ENDPOINT_HALT */ + setup_set_stall.wIndex = epno; + setup_set_stall.wLength = 0; + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup_get_status); + setup_get_status.bmRequestType = 0x82; /* read endpoint */ + setup_get_status.bRequest = 0x00; /* get status */ + setup_get_status.wValue = 0x00; + setup_get_status.wIndex = epno; + setup_get_status.wLength = 1; + + if (libusb20_dev_check_connected(pdev) != 0) { + printf("Device disconnected\n"); + break; + } + pxfer = libusb20_tr_get_pointer(pdev, 0); + + error = libusb20_tr_open(pxfer, 1, 1, epno); + + if (error != 0) { + printf("Endpoint 0x%02x does not exist " + "in current setting. (%s, ignored)\n", + epno, libusb20_strerror(error)); + continue; + } + printf("Stalling endpoint 0x%02x\n", epno); + + /* set stall */ + error = libusb20_dev_request_sync(pdev, + &setup_set_stall, NULL, NULL, 250, 0); + + if (error != 0) { + printf("Endpoint 0x%02x does not allow " + "setting of stall. (%s)\n", + epno, libusb20_strerror(error)); + errcnt++; + } + /* get EP status */ + buf[0] = 0; + error = libusb20_dev_request_sync(pdev, + &setup_get_status, buf, NULL, 250, 0); + + if (error != 0) { + printf("Endpoint 0x%02x does not allow " + "reading status. (%s)\n", + epno, libusb20_strerror(error)); + errcnt++; + } else { + if (!(buf[0] & 1)) { + printf("Endpoint 0x%02x status is " + "not set to stalled\n", epno); + errcnt++; + } + } + + buf[0] = 0; + error = libusb20_tr_bulk_intr_sync(pxfer, buf, 1, NULL, 250); + if (error != LIBUSB20_TRANSFER_STALL) { + printf("Endpoint 0x%02x does not appear to " + "have stalled. Missing stall PID!\n", epno); + errcnt++; + } + printf("Unstalling endpoint 0x%02x\n", epno); + + libusb20_tr_clear_stall_sync(pxfer); + + /* get EP status */ + buf[0] = 0; + error = libusb20_dev_request_sync(pdev, + &setup_get_status, buf, NULL, 250, 0); + + if (error != 0) { + printf("Endpoint 0x%02x does not allow " + "reading status. (%s)\n", + epno, libusb20_strerror(error)); + errcnt++; + } else { + if (buf[0] & 1) { + printf("Endpoint 0x%02x status is " + "still stalled\n", epno); + errcnt++; + } + } + + libusb20_tr_close(pxfer); + iter++; + } + + libusb20_dev_free(pdev); + + printf("\n" + "Test summary\n" + "============\n" + "Endpoints tested: %d\n" + "Errors: %d\n", iter, errcnt); +} + +void +usb_set_alt_interface_test(uint16_t vid, uint16_t pid) +{ + struct libusb20_device *pdev; + struct libusb20_config *config; + + int iter; + int error; + int errcnt; + int n; + int m; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + printf("Starting set alternate setting test " + "for VID=0x%04x PID=0x%04x\n", vid, pid); + + config = libusb20_dev_alloc_config(pdev, + libusb20_dev_get_config_index(pdev)); + if (config == NULL) { + printf("Could not get configuration descriptor\n"); + libusb20_dev_free(pdev); + return; + } + iter = 0; + errcnt = 0; + + for (n = 0; n != config->num_interface; n++) { + /* detach kernel driver */ + libusb20_dev_detach_kernel_driver(pdev, n); + + error = libusb20_dev_open(pdev, 0); + if (error) + printf("ERROR could not open device\n"); + + /* Try the alternate settings */ + for (m = 0; m != config->interface[n].num_altsetting; m++) { + + iter++; + + if (libusb20_dev_set_alt_index(pdev, n, m + 1)) { + printf("ERROR on interface %d alt %d\n", n, m + 1); + errcnt++; + } + } + + /* Restore to default */ + + iter++; + + if (libusb20_dev_set_alt_index(pdev, n, 0)) { + printf("ERROR on interface %d alt %d\n", n, 0); + errcnt++; + } + libusb20_dev_close(pdev); + } + + libusb20_dev_free(pdev); + + printf("\n" + "Test summary\n" + "============\n" + "Interfaces tested: %d\n" + "Errors: %d\n", iter, errcnt); +} diff --git a/tools/tools/usbtest/usb_modem_test.c b/tools/tools/usbtest/usb_modem_test.c new file mode 100644 index 0000000..74406fc --- /dev/null +++ b/tools/tools/usbtest/usb_modem_test.c @@ -0,0 +1,585 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2007-2010 Hans Petter Selasky. 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <err.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <libusb20.h> +#include <libusb20_desc.h> + +#include <dev/usb/usb_endian.h> +#include <dev/usb/usb.h> +#include <dev/usb/usb_cdc.h> + +#include "usbtest.h" + +static struct modem { + struct libusb20_transfer *xfer_in; + struct libusb20_transfer *xfer_out; + struct libusb20_device *usb_dev; + + struct bps rx_bytes; + struct bps tx_bytes; + uint32_t c0; + uint32_t c1; + uint32_t out_state; + uint32_t in_last; + uint32_t in_synced; + uint32_t duration; + uint32_t errors; + + uint8_t use_vendor_specific; + uint8_t loop_data; + uint8_t modem_at_mode; + uint8_t data_stress_test; + uint8_t control_ep_test; + uint8_t usb_iface; + uint8_t random_tx_length; + uint8_t random_tx_delay; + +} modem; + +static void +set_defaults(struct modem *p) +{ + memset(p, 0, sizeof(*p)); + + p->data_stress_test = 1; + p->control_ep_test = 1; + p->duration = 60; /* seconds */ +} + +void +do_bps(const char *desc, struct bps *bps, uint32_t len) +{ + bps->bytes += len; +} + +static void +modem_out_state(uint8_t *buf) +{ + if (modem.modem_at_mode) { + switch (modem.out_state & 3) { + case 0: + *buf = 'A'; + break; + case 1: + *buf = 'T'; + break; + case 2: + *buf = '\r'; + break; + default: + *buf = '\n'; + modem.c0++; + break; + } + modem.out_state++; + } else { + *buf = modem.out_state; + modem.out_state++; + modem.out_state %= 255; + } +} + +static void +modem_in_state(uint8_t buf, uint32_t counter) +{ + if ((modem.in_last == 'O') && (buf == 'K')) { + modem.c1++; + modem.in_last = buf; + } else if (buf == modem.in_last) { + modem.c1++; + modem.in_last++; + modem.in_last %= 255; + if (modem.in_synced == 0) { + if (modem.errors < 64) { + printf("Got sync\n"); + } + modem.in_synced = 1; + } + } else { + if (modem.in_synced) { + if (modem.errors < 64) { + printf("Lost sync @ %d, 0x%02x != 0x%02x\n", + counter % 512, buf, modem.in_last); + } + modem.in_synced = 0; + modem.errors++; + } + modem.in_last = buf; + modem.in_last++; + modem.in_last %= 255; + } +} + +static void +modem_write(uint8_t *buf, uint32_t len) +{ + uint32_t n; + + for (n = 0; n != len; n++) { + modem_out_state(buf + n); + } + + do_bps("transmitted", &modem.tx_bytes, len); +} + +static void +modem_read(uint8_t *buf, uint32_t len) +{ + uint32_t n; + + for (n = 0; n != len; n++) { + modem_in_state(buf[n], n); + } + + do_bps("received", &modem.rx_bytes, len); +} + +static void +usb_modem_control_ep_test(struct modem *p, uint32_t duration, uint8_t flag) +{ + struct timeval sub_tv; + struct timeval ref_tv; + struct timeval res_tv; + struct LIBUSB20_CONTROL_SETUP_DECODED setup; + struct usb_cdc_abstract_state ast; + struct usb_cdc_line_state ls; + uint16_t feature = UCDC_ABSTRACT_STATE; + uint16_t state = UCDC_DATA_MULTIPLEXED; + uint8_t iface_no; + uint8_t buf[4]; + int id = 0; + int iter = 0; + + time_t last_sec; + + iface_no = p->usb_iface - 1; + + gettimeofday(&ref_tv, 0); + + last_sec = ref_tv.tv_sec; + + printf("\nTest=%d\n", (int)flag); + + while (1) { + + gettimeofday(&sub_tv, 0); + + if (last_sec != sub_tv.tv_sec) { + + printf("STATUS: ID=%u, COUNT=%u tests/sec ERR=%u\n", + (int)id, + (int)iter, + (int)p->errors); + + fflush(stdout); + + last_sec = sub_tv.tv_sec; + + id++; + + iter = 0; + } + timersub(&sub_tv, &ref_tv, &res_tv); + + if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) + break; + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); + + if (flag & 1) { + setup.bmRequestType = UT_READ_CLASS_INTERFACE; + setup.bRequest = 0x03; + setup.wValue = 0x0001; + setup.wIndex = iface_no; + setup.wLength = 0x0002; + + if (libusb20_dev_request_sync(p->usb_dev, &setup, buf, NULL, 250, 0)) { + p->errors++; + } + } + if (flag & 2) { + setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; + setup.bRequest = UCDC_SET_COMM_FEATURE; + setup.wValue = feature; + setup.wIndex = iface_no; + setup.wLength = UCDC_ABSTRACT_STATE_LENGTH; + USETW(ast.wState, state); + + if (libusb20_dev_request_sync(p->usb_dev, &setup, &ast, NULL, 250, 0)) { + p->errors++; + } + } + if (flag & 4) { + USETDW(ls.dwDTERate, 115200); + ls.bCharFormat = UCDC_STOP_BIT_1; + ls.bParityType = UCDC_PARITY_NONE; + ls.bDataBits = 8; + + setup.bmRequestType = UT_WRITE_CLASS_INTERFACE; + setup.bRequest = UCDC_SET_LINE_CODING; + setup.wValue = 0; + setup.wIndex = iface_no; + setup.wLength = sizeof(ls); + + if (libusb20_dev_request_sync(p->usb_dev, &setup, &ls, NULL, 250, 0)) { + p->errors++; + } + } + iter++; + } + + printf("\nModem control endpoint test done!\n"); +} + +static void +usb_modem_data_stress_test(struct modem *p, uint32_t duration) +{ + struct timeval sub_tv; + struct timeval ref_tv; + struct timeval res_tv; + + time_t last_sec; + + uint8_t in_pending = 0; + uint8_t in_ready = 0; + uint8_t out_pending = 0; + + uint32_t id = 0; + + uint32_t in_max; + uint32_t out_max; + uint32_t io_max; + + uint8_t *in_buffer = 0; + uint8_t *out_buffer = 0; + + gettimeofday(&ref_tv, 0); + + last_sec = ref_tv.tv_sec; + + printf("\n"); + + in_max = libusb20_tr_get_max_total_length(p->xfer_in); + out_max = libusb20_tr_get_max_total_length(p->xfer_out); + + /* get the smallest buffer size and use that */ + io_max = (in_max < out_max) ? in_max : out_max; + + if (in_max != out_max) + printf("WARNING: Buffer sizes are un-equal: %u vs %u\n", in_max, out_max); + + in_buffer = malloc(io_max); + if (in_buffer == NULL) + goto fail; + + out_buffer = malloc(io_max); + if (out_buffer == NULL) + goto fail; + + while (1) { + + gettimeofday(&sub_tv, 0); + + if (last_sec != sub_tv.tv_sec) { + + printf("STATUS: ID=%u, RX=%u bytes/sec, TX=%u bytes/sec, ERR=%d\n", + (int)id, + (int)p->rx_bytes.bytes, + (int)p->tx_bytes.bytes, + (int)p->errors); + + p->rx_bytes.bytes = 0; + p->tx_bytes.bytes = 0; + + fflush(stdout); + + last_sec = sub_tv.tv_sec; + + id++; + } + timersub(&sub_tv, &ref_tv, &res_tv); + + if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)duration)) + break; + + libusb20_dev_process(p->usb_dev); + + if (!libusb20_tr_pending(p->xfer_in)) { + if (in_pending) { + if (libusb20_tr_get_status(p->xfer_in) == 0) { + modem_read(in_buffer, libusb20_tr_get_length(p->xfer_in, 0)); + } else { + p->errors++; + usleep(10000); + } + in_pending = 0; + in_ready = 1; + } + if (p->loop_data == 0) { + libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0); + libusb20_tr_start(p->xfer_in); + in_pending = 1; + in_ready = 0; + } + } + if (!libusb20_tr_pending(p->xfer_out)) { + + uint32_t len; + uint32_t dly; + + if (out_pending) { + if (libusb20_tr_get_status(p->xfer_out) != 0) { + p->errors++; + usleep(10000); + } + } + if (p->random_tx_length) { + len = ((uint32_t)usb_ts_rand_noise()) % ((uint32_t)io_max); + } else { + len = io_max; + } + + if (p->random_tx_delay) { + dly = ((uint32_t)usb_ts_rand_noise()) % 16000U; + } else { + dly = 0; + } + + if (p->loop_data != 0) { + if (in_ready != 0) { + len = libusb20_tr_get_length(p->xfer_in, 0); + memcpy(out_buffer, in_buffer, len); + in_ready = 0; + } else { + len = io_max + 1; + } + if (!libusb20_tr_pending(p->xfer_in)) { + libusb20_tr_setup_bulk(p->xfer_in, in_buffer, io_max, 0); + libusb20_tr_start(p->xfer_in); + in_pending = 1; + } + } else { + modem_write(out_buffer, len); + } + + if (len <= io_max) { + libusb20_tr_setup_bulk(p->xfer_out, out_buffer, len, 0); + + if (dly != 0) + usleep(dly); + + libusb20_tr_start(p->xfer_out); + + out_pending = 1; + } + } + libusb20_dev_wait_process(p->usb_dev, 500); + + if (libusb20_dev_check_connected(p->usb_dev) != 0) { + printf("Device disconnected\n"); + break; + } + } + + libusb20_tr_stop(p->xfer_in); + libusb20_tr_stop(p->xfer_out); + + printf("\nData stress test done!\n"); + +fail: + if (in_buffer) + free(in_buffer); + if (out_buffer) + free(out_buffer); +} + +static void +exec_host_modem_test(struct modem *p, uint16_t vid, uint16_t pid) +{ + struct libusb20_device *pdev; + + uint8_t ntest = 0; + uint8_t x; + uint8_t in_ep; + uint8_t out_ep; + uint8_t iface; + + int error; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + + if (p->use_vendor_specific) + find_usb_endpoints(pdev, 255, 255, 255, 0, &iface, &in_ep, &out_ep, 0); + else + find_usb_endpoints(pdev, 2, 2, 1, 0, &iface, &in_ep, &out_ep, 1); + + if ((in_ep == 0) || (out_ep == 0)) { + printf("Could not find USB endpoints\n"); + libusb20_dev_free(pdev); + return; + } + printf("Attaching to: %s @ iface %d\n", + libusb20_dev_get_desc(pdev), iface); + + if (libusb20_dev_open(pdev, 2)) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + if (libusb20_dev_detach_kernel_driver(pdev, iface)) { + printf("WARNING: Could not detach kernel driver\n"); + } + p->xfer_in = libusb20_tr_get_pointer(pdev, 0); + error = libusb20_tr_open(p->xfer_in, 65536 / 4, 1, in_ep); + if (error) { + printf("Could not open USB endpoint %d\n", in_ep); + libusb20_dev_free(pdev); + return; + } + p->xfer_out = libusb20_tr_get_pointer(pdev, 1); + error = libusb20_tr_open(p->xfer_out, 65536 / 4, 1, out_ep); + if (error) { + printf("Could not open USB endpoint %d\n", out_ep); + libusb20_dev_free(pdev); + return; + } + p->usb_dev = pdev; + p->usb_iface = iface; + p->errors = 0; + + if (p->control_ep_test) + ntest += 7; + + if (p->data_stress_test) + ntest += 1; + + if (ntest == 0) { + printf("No tests selected\n"); + } else { + + if (p->control_ep_test) { + for (x = 1; x != 8; x++) { + usb_modem_control_ep_test(p, + (p->duration + ntest - 1) / ntest, x); + } + } + if (p->data_stress_test) { + usb_modem_data_stress_test(p, + (p->duration + ntest - 1) / ntest); + } + } + + printf("\nDone\n"); + + libusb20_dev_free(pdev); +} + +void +show_host_modem_test(uint8_t level, uint16_t vid, uint16_t pid, uint32_t duration) +{ + uint8_t retval; + + set_defaults(&modem); + + modem.duration = duration; + + while (1) { + + retval = usb_ts_show_menu(level, "Modem Test Parameters", + " 1) Execute Data Stress Test: <%s>\n" + " 2) Execute Modem Control Endpoint Test: <%s>\n" + " 3) Use random transmit length: <%s>\n" + " 4) Use random transmit delay: <%s> ms\n" + " 5) Use vendor specific interface: <%s>\n" + "10) Loop data: <%s>\n" + "13) Set test duration: <%d> seconds\n" + "20) Reset parameters\n" + "30) Start test (VID=0x%04x, PID=0x%04x)\n" + "40) Select another device\n" + " x) Return to previous menu \n", + (modem.data_stress_test ? "YES" : "NO"), + (modem.control_ep_test ? "YES" : "NO"), + (modem.random_tx_length ? "YES" : "NO"), + (modem.random_tx_delay ? "16" : "0"), + (modem.use_vendor_specific ? "YES" : "NO"), + (modem.loop_data ? "YES" : "NO"), + (int)(modem.duration), + (int)vid, (int)pid); + + switch (retval) { + case 0: + break; + case 1: + modem.data_stress_test ^= 1; + break; + case 2: + modem.control_ep_test ^= 1; + break; + case 3: + modem.random_tx_length ^= 1; + break; + case 4: + modem.random_tx_delay ^= 1; + break; + case 5: + modem.use_vendor_specific ^= 1; + modem.control_ep_test = 0; + break; + case 10: + modem.loop_data ^= 1; + break; + case 13: + modem.duration = get_integer(); + break; + case 20: + set_defaults(&modem); + break; + case 30: + exec_host_modem_test(&modem, vid, pid); + break; + case 40: + show_host_device_selection(level + 1, &vid, &pid); + break; + default: + return; + } + } +} diff --git a/tools/tools/usbtest/usb_msc_test.c b/tools/tools/usbtest/usb_msc_test.c new file mode 100644 index 0000000..f98b549 --- /dev/null +++ b/tools/tools/usbtest/usb_msc_test.c @@ -0,0 +1,1290 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2007-2012 Hans Petter Selasky. 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 <stdio.h> +#include <stdint.h> +#include <stdlib.h> +#include <err.h> +#include <string.h> +#include <errno.h> +#include <unistd.h> + +#include <sys/sysctl.h> +#include <sys/time.h> + +#include <libusb20.h> +#include <libusb20_desc.h> + +#include <dev/usb/usb_endian.h> + +#include "usbtest.h" + +#include "usb_msc_test.h" + +/* Command Block Wrapper */ +typedef struct { + uDWord dCBWSignature; +#define CBWSIGNATURE 0x43425355 + uDWord dCBWTag; + uDWord dCBWDataTransferLength; + uByte bCBWFlags; +#define CBWFLAGS_OUT 0x00 +#define CBWFLAGS_IN 0x80 + uByte bCBWLUN; + uByte bCDBLength; +#define CBWCDBLENGTH 16 + uByte CBWCDB[CBWCDBLENGTH]; +} umass_bbb_cbw_t; + +#define UMASS_BBB_CBW_SIZE 31 + +/* Command Status Wrapper */ +typedef struct { + uDWord dCSWSignature; +#define CSWSIGNATURE 0x53425355 +#define CSWSIGNATURE_IMAGINATION_DBX1 0x43425355 +#define CSWSIGNATURE_OLYMPUS_C1 0x55425355 + uDWord dCSWTag; + uDWord dCSWDataResidue; + uByte bCSWStatus; +#define CSWSTATUS_GOOD 0x0 +#define CSWSTATUS_FAILED 0x1 +#define CSWSTATUS_PHASE 0x2 +} umass_bbb_csw_t; + +#define UMASS_BBB_CSW_SIZE 13 + +#define SC_READ_6 0x08 +#define SC_READ_10 0x28 +#define SC_READ_12 0xa8 +#define SC_WRITE_6 0x0a +#define SC_WRITE_10 0x2a +#define SC_WRITE_12 0xaa + +static struct stats { + uint64_t xfer_error; + uint64_t xfer_success; + uint64_t xfer_reset; + uint64_t xfer_rx_bytes; + uint64_t xfer_tx_bytes; + uint64_t data_error; +} stats; + +static uint32_t xfer_current_id; +static uint32_t xfer_wrapper_sig; +static uint32_t block_size = 512; + +static struct libusb20_transfer *xfer_in; +static struct libusb20_transfer *xfer_out; +static struct libusb20_device *usb_pdev; +static uint8_t usb_iface; +static int sense_recurse; + +/* + * SCSI commands sniffed off the wire - LUN maybe needs to be + * adjusted! Refer to "dev/usb/storage/ustorage_fs.c" for more + * information. + */ +static uint8_t mode_sense_6[0x6] = {0x1a, 0, 0x3f, 0, 0x0c}; +static uint8_t read_capacity[0xA] = {0x25,}; +static uint8_t request_sense[0xC] = {0x03, 0, 0, 0, 0x12}; +static uint8_t test_unit_ready[0x6] = {0}; +static uint8_t mode_page_inquiry[0x6] = {0x12, 1, 0x80, 0, 0xff, 0}; +static uint8_t request_invalid[0xC] = {0xEA, 0, 0, 0, 0}; +static uint8_t prevent_removal[0x6] = {0x1E, 0, 0, 0, 1}; +static uint8_t read_toc[0xA] = {0x43, 0x02, 0, 0, 0, 0xAA, 0, 0x0C}; + +#define TIMEOUT_FILTER(x) (x) + +static void usb_request_sense(uint8_t lun); + +static void +do_msc_reset(uint8_t lun) +{ + struct LIBUSB20_CONTROL_SETUP_DECODED setup; + + LIBUSB20_INIT(LIBUSB20_CONTROL_SETUP, &setup); + + setup.bmRequestType = LIBUSB20_REQUEST_TYPE_CLASS | + LIBUSB20_RECIPIENT_INTERFACE; + setup.bRequest = 0xFF; /* BBB reset */ + setup.wValue = 0; + setup.wIndex = usb_iface; + setup.wLength = 0; + + if (libusb20_dev_request_sync(usb_pdev, &setup, NULL, NULL, 5000, 0)) { + printf("ERROR: %s\n", __FUNCTION__); + stats.xfer_error++; + } + libusb20_tr_clear_stall_sync(xfer_in); + libusb20_tr_clear_stall_sync(xfer_out); + + stats.xfer_reset++; + + usb_request_sense(lun); +} + +static uint8_t +do_msc_cmd(uint8_t *pcmd, uint8_t cmdlen, void *pdata, uint32_t datalen, + uint8_t isread, uint8_t isshort, uint8_t lun, uint8_t flags) +{ + umass_bbb_cbw_t cbw; + umass_bbb_csw_t csw; + struct libusb20_transfer *xfer_io; + uint32_t actlen; + uint32_t timeout; + int error; + + memset(&cbw, 0, sizeof(cbw)); + + USETDW(cbw.dCBWSignature, xfer_wrapper_sig); + USETDW(cbw.dCBWTag, xfer_current_id); + xfer_current_id++; + USETDW(cbw.dCBWDataTransferLength, datalen); + cbw.bCBWFlags = (isread ? CBWFLAGS_IN : CBWFLAGS_OUT); + cbw.bCBWLUN = lun; + cbw.bCDBLength = cmdlen; + bcopy(pcmd, cbw.CBWCDB, cmdlen); + + actlen = 0; + + timeout = ((datalen + 299999) / 300000) * 1000; + timeout += 5000; + + if ((error = libusb20_tr_bulk_intr_sync(xfer_out, + &cbw, sizeof(cbw), &actlen, TIMEOUT_FILTER(1000)))) { + printf("ERROR: CBW reception: %d\n", error); + do_msc_reset(lun); + return (1); + } + if (actlen != sizeof(cbw)) { + printf("ERROR: CBW length: %d != %d\n", + actlen, (int)sizeof(cbw)); + do_msc_reset(lun); + return (1); + } + if (flags & 1) + datalen /= 2; + + if (datalen != 0) { + xfer_io = isread ? xfer_in : xfer_out; + + if ((error = libusb20_tr_bulk_intr_sync(xfer_io, + pdata, datalen, &actlen, TIMEOUT_FILTER(timeout)))) { + printf("ERROR: Data transfer: %d\n", error); + do_msc_reset(lun); + return (1); + } + if ((actlen != datalen) && (!isshort)) { + printf("ERROR: Short data: %d of %d bytes\n", + actlen, datalen); + do_msc_reset(lun); + return (1); + } + } + actlen = 0; + timeout = 8; + + do { + error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, + sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); + if (error) { + if (error == LIBUSB20_TRANSFER_TIMED_OUT) { + printf("TIMEOUT: Trying to get CSW again. " + "%d tries left.\n", timeout); + } else { + break; + } + } else { + break; + } + } while (--timeout); + + if (error) { + libusb20_tr_clear_stall_sync(xfer_in); + error = libusb20_tr_bulk_intr_sync(xfer_in, &csw, + sizeof(csw), &actlen, TIMEOUT_FILTER(1000)); + if (error) { + libusb20_tr_clear_stall_sync(xfer_in); + printf("ERROR: Could not read CSW: Stalled or " + "timeout (%d).\n", error); + do_msc_reset(lun); + return (1); + } + } + if (UGETDW(csw.dCSWSignature) != CSWSIGNATURE) { + printf("ERROR: Wrong CSW signature\n"); + do_msc_reset(lun); + return (1); + } + if (actlen != sizeof(csw)) { + printf("ERROR: Wrong CSW length: %d != %d\n", + actlen, (int)sizeof(csw)); + do_msc_reset(lun); + return (1); + } + if (csw.bCSWStatus != 0) { + printf("ERROR: CSW status: %d\n", (int)csw.bCSWStatus); + return (1); + } else { + stats.xfer_success++; + return (0); + } +} + +static uint8_t +do_read_10(uint32_t lba, uint32_t len, void *buf, uint8_t lun) +{ + static uint8_t cmd[10]; + uint8_t retval; + + cmd[0] = SC_READ_10; + + len /= block_size; + + cmd[2] = lba >> 24; + cmd[3] = lba >> 16; + cmd[4] = lba >> 8; + cmd[5] = lba >> 0; + + cmd[7] = len >> 8; + cmd[8] = len; + + retval = do_msc_cmd(cmd, 10, buf, len * block_size, 1, 0, lun, 0); + + if (retval) { + printf("ERROR: %s\n", __FUNCTION__); + stats.xfer_error++; + } + return (retval); +} + +static uint8_t +do_write_10(uint32_t lba, uint32_t len, void *buf, uint8_t lun) +{ + static uint8_t cmd[10]; + uint8_t retval; + uint8_t abort; + + cmd[0] = SC_WRITE_10; + + abort = len & 1; + + len /= block_size; + + cmd[2] = lba >> 24; + cmd[3] = lba >> 16; + cmd[4] = lba >> 8; + cmd[5] = lba >> 0; + + cmd[7] = len >> 8; + cmd[8] = len; + + retval = do_msc_cmd(cmd, 10, buf, (len * block_size), 0, 0, lun, abort); + + if (retval) { + printf("ERROR: %s\n", __FUNCTION__); + stats.xfer_error++; + } + return (retval); +} + +static void +do_io_test(struct usb_msc_params *p, uint8_t lun, uint32_t lba_max, + uint8_t *buffer, uint8_t *reference) +{ + uint32_t io_offset; + uint32_t io_size; + uint32_t temp; + uint8_t do_read; + uint8_t retval; + + switch (p->io_mode) { + case USB_MSC_IO_MODE_WRITE_ONLY: + do_read = 0; + break; + case USB_MSC_IO_MODE_READ_WRITE: + do_read = (usb_ts_rand_noise() & 1); + break; + default: + do_read = 1; + break; + } + + switch (p->io_offset) { + case USB_MSC_IO_OFF_RANDOM: + io_offset = usb_ts_rand_noise(); + break; + default: + io_offset = 0; + break; + } + + switch (p->io_delay) { + case USB_MSC_IO_DELAY_RANDOM_10MS: + usleep(((uint32_t)usb_ts_rand_noise()) % 10000U); + break; + case USB_MSC_IO_DELAY_RANDOM_100MS: + usleep(((uint32_t)usb_ts_rand_noise()) % 100000U); + break; + case USB_MSC_IO_DELAY_FIXED_10MS: + usleep(10000); + break; + case USB_MSC_IO_DELAY_FIXED_100MS: + usleep(100000); + break; + default: + break; + } + + switch (p->io_size) { + case USB_MSC_IO_SIZE_RANDOM: + io_size = ((uint32_t)usb_ts_rand_noise()) & 65535U; + break; + case USB_MSC_IO_SIZE_INCREASING: + io_size = (xfer_current_id & 65535U); + break; + case USB_MSC_IO_SIZE_FIXED_1BLK: + io_size = 1; + break; + case USB_MSC_IO_SIZE_FIXED_2BLK: + io_size = 2; + break; + case USB_MSC_IO_SIZE_FIXED_4BLK: + io_size = 4; + break; + case USB_MSC_IO_SIZE_FIXED_8BLK: + io_size = 8; + break; + case USB_MSC_IO_SIZE_FIXED_16BLK: + io_size = 16; + break; + case USB_MSC_IO_SIZE_FIXED_32BLK: + io_size = 32; + break; + case USB_MSC_IO_SIZE_FIXED_64BLK: + io_size = 64; + break; + case USB_MSC_IO_SIZE_FIXED_128BLK: + io_size = 128; + break; + case USB_MSC_IO_SIZE_FIXED_256BLK: + io_size = 256; + break; + case USB_MSC_IO_SIZE_FIXED_512BLK: + io_size = 512; + break; + case USB_MSC_IO_SIZE_FIXED_1024BLK: + io_size = 1024; + break; + default: + io_size = 1; + break; + } + + if (io_size == 0) + io_size = 1; + + io_offset %= lba_max; + + temp = (lba_max - io_offset); + + if (io_size > temp) + io_size = temp; + + if (do_read) { + retval = do_read_10(io_offset, io_size * block_size, + buffer + (io_offset * block_size), lun); + + if (retval == 0) { + if (bcmp(buffer + (io_offset * block_size), + reference + (io_offset * block_size), + io_size * block_size)) { + printf("ERROR: Data comparison failure\n"); + stats.data_error++; + retval = 1; + } + } + stats.xfer_rx_bytes += (io_size * block_size); + + } else { + + retval = do_write_10(io_offset, io_size * block_size, + reference + (io_offset * block_size), lun); + + stats.xfer_tx_bytes += (io_size * block_size); + } + + if ((stats.xfer_error + stats.data_error + + stats.xfer_reset) >= p->max_errors) { + printf("Maximum number of errors exceeded\n"); + p->done = 1; + } +} + +static void +usb_request_sense(uint8_t lun) +{ + uint8_t dummy_buf[255]; + + if (sense_recurse) + return; + + sense_recurse++; + + do_msc_cmd(request_sense, sizeof(request_sense), + dummy_buf, 255, 1, 1, lun, 0); + + sense_recurse--; +} + +static void +usb_msc_test(struct usb_msc_params *p) +{ + struct stats last_stat; + struct timeval sub_tv; + struct timeval ref_tv; + struct timeval res_tv; + uint8_t *buffer = NULL; + uint8_t *reference = NULL; + uint32_t dummy_buf[65536 / 4]; + uint32_t lba_max; + uint32_t x; + uint32_t y; + uint32_t capacity_lba; + uint32_t capacity_bs; + time_t last_sec; + uint8_t lun; + int tries; + + memset(&last_stat, 0, sizeof(last_stat)); + + switch (p->io_lun) { + case USB_MSC_IO_LUN_0: + lun = 0; + break; + case USB_MSC_IO_LUN_1: + lun = 1; + break; + case USB_MSC_IO_LUN_2: + lun = 2; + break; + case USB_MSC_IO_LUN_3: + lun = 3; + break; + default: + lun = 0; + break; + } + + p->done = 0; + + sense_recurse = p->try_sense_on_error ? 0 : 1; + + printf("Resetting device ...\n"); + + do_msc_reset(lun); + + printf("Testing SCSI commands ...\n"); + + if (p->try_all_lun) { + printf("Requesting sense from LUN 0..255 ... "); + for (x = y = 0; x != 256; x++) { + if (do_msc_cmd(mode_sense_6, sizeof(mode_sense_6), + dummy_buf, 255, 1, 1, x, 0)) + y++; + + if (libusb20_dev_check_connected(usb_pdev) != 0) { + printf(" disconnect "); + break; + } + } + printf("Passed=%d, Failed=%d\n", 256 - y, y); + } + do_msc_cmd(mode_sense_6, sizeof(mode_sense_6), + dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(request_sense, sizeof(request_sense), + dummy_buf, 255, 1, 1, lun, 0); + + for (tries = 0; tries != 4; tries++) { + + memset(dummy_buf, 0, sizeof(dummy_buf)); + + if (do_msc_cmd(read_capacity, sizeof(read_capacity), + dummy_buf, 255, 1, 1, lun, 0) != 0) { + printf("Cannot read disk capacity (%u / 4)\n", tries); + if (tries == 3) + return; + usleep(50000); + continue; + } else { + break; + } + } + + capacity_lba = be32toh(dummy_buf[0]); + capacity_bs = be32toh(dummy_buf[1]); + + printf("Disk reports a capacity of LBA=%u and BS=%u\n", + capacity_lba, capacity_bs); + + block_size = capacity_bs; + + if (capacity_bs > 65535) { + printf("Blocksize is too big\n"); + return; + } + if (capacity_bs < 1) { + printf("Blocksize is too small\n"); + return; + } + if (capacity_bs != 512) + printf("INFO: Blocksize is not 512 bytes\n"); + + if (p->try_invalid_scsi_command) { + int status; + + for (tries = 0; tries != 4; tries++) { + + printf("Trying invalid SCSI command: "); + + status = do_msc_cmd(request_invalid, + sizeof(request_invalid), dummy_buf, + 255, 1, 1, lun, 0); + + printf("Result%s as expected\n", status ? "" : " NOT"); + + usleep(50000); + } + } + if (p->try_invalid_wrapper_block) { + int status; + + for (tries = 0; tries != 4; tries++) { + + printf("Trying invalid USB wrapper block signature: "); + + xfer_wrapper_sig = 0x55663322; + + status = do_msc_cmd(read_capacity, + sizeof(read_capacity), dummy_buf, + 255, 1, 1, lun, 0); + + printf("Result%s as expected\n", status ? "" : " NOT"); + + xfer_wrapper_sig = CBWSIGNATURE; + + usleep(50000); + } + } + do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(request_sense, sizeof(request_sense), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(test_unit_ready, sizeof(test_unit_ready), 0, 0, 1, 1, lun, 0); + do_msc_cmd(read_capacity, sizeof(read_capacity), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0); + do_msc_cmd(mode_page_inquiry, sizeof(mode_page_inquiry), dummy_buf, 255, 1, 1, lun, 0); + + if (do_msc_cmd(prevent_removal, sizeof(prevent_removal), + 0, 0, 1, 1, lun, 0)) { + printf("INFO: Prevent medium removal failed\n"); + } + if (do_msc_cmd(read_toc, sizeof(read_toc), + dummy_buf, 255, 1, 1, lun, 0)) { + printf("INFO: Read Table Of Content failed\n"); + } + if (p->try_last_lba) { + + for (y = 0, x = (1UL << 31); x; x >>= 1) { + if (do_read_10(x | y, block_size, dummy_buf, lun) == 0) + y |= x; + } + + printf("Highest readable LBA: %u (%s), " + "Capacity is %u MBytes\n", y, + (capacity_lba != y) ? "WRONG" : "OK", + (int)((((uint64_t)(y) * (uint64_t)block_size) + + (uint64_t)block_size) / 1000000ULL)); + } else { + + y = capacity_lba; + + printf("Highest readable LBA: %u (not " + "verified), Capacity is %u MBytes\n", y, + (int)((((uint64_t)(y) * (uint64_t)block_size) + + (uint64_t)block_size) / 1000000ULL)); + } + + if (y != 0xFFFFFFFFU) + y++; + + lba_max = y; + + switch (p->io_area) { + case USB_MSC_IO_AREA_1MB: + lba_max = 1024; + break; + case USB_MSC_IO_AREA_16MB: + lba_max = 1024 * 16; + break; + case USB_MSC_IO_AREA_256MB: + lba_max = 1024 * 256; + break; + case USB_MSC_IO_AREA_COMPLETE: + default: + break; + } + + if (lba_max > 65535) + lba_max = 65535; + + printf("Highest testable LBA: %u\n", (int)lba_max); + + buffer = malloc(block_size * lba_max); + if (buffer == NULL) { + printf("ERROR: Could not allocate memory\n"); + goto fail; + } + reference = malloc(block_size * lba_max); + if (reference == NULL) { + printf("ERROR: Could not allocate memory\n"); + goto fail; + } +retry_read_init: + + printf("Setting up initial data pattern, " + "LBA limit = %u ... ", lba_max); + + switch (p->io_mode) { + case USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY: + case USB_MSC_IO_MODE_WRITE_ONLY: + case USB_MSC_IO_MODE_READ_WRITE: + + switch (p->io_pattern) { + case USB_MSC_IO_PATTERN_FIXED: + for (x = 0; x != (block_size * lba_max); x += 8) { + reference[x + 0] = x >> 24; + reference[x + 1] = x >> 16; + reference[x + 2] = x >> 8; + reference[x + 3] = x >> 0; + reference[x + 4] = 0xFF; + reference[x + 5] = 0x00; + reference[x + 6] = 0xFF; + reference[x + 7] = 0x00; + } + if (do_write_10(0, lba_max * block_size, + reference, lun)) { + printf("FAILED\n"); + lba_max /= 2; + if (lba_max) + goto retry_read_init; + goto fail; + } + printf("SUCCESS\n"); + break; + case USB_MSC_IO_PATTERN_RANDOM: + for (x = 0; x != (block_size * lba_max); x++) { + reference[x] = usb_ts_rand_noise() % 255U; + } + if (do_write_10(0, lba_max * block_size, + reference, lun)) { + printf("FAILED\n"); + lba_max /= 2; + if (lba_max) + goto retry_read_init; + goto fail; + } + printf("SUCCESS\n"); + break; + default: + if (do_read_10(0, lba_max * block_size, + reference, lun)) { + printf("FAILED\n"); + lba_max /= 2; + if (lba_max) + goto retry_read_init; + goto fail; + } + printf("SUCCESS\n"); + break; + } + break; + + default: + if (do_read_10(0, lba_max * block_size, reference, lun)) { + printf("FAILED\n"); + lba_max /= 2; + if (lba_max) + goto retry_read_init; + goto fail; + } + printf("SUCCESS\n"); + break; + } + + + if (p->try_abort_data_write) { + if (do_write_10(0, (2 * block_size) | 1, reference, lun)) + printf("Aborted data write failed (OK)!\n"); + else + printf("Aborted data write did not fail (ERROR)!\n"); + + if (do_read_10(0, (2 * block_size), reference, lun)) + printf("Post-aborted data read failed (ERROR)\n"); + else + printf("Post-aborted data read success (OK)!\n"); + } + printf("Starting test ...\n"); + + gettimeofday(&ref_tv, 0); + + last_sec = ref_tv.tv_sec; + + printf("\n"); + + while (1) { + + gettimeofday(&sub_tv, 0); + + if (last_sec != sub_tv.tv_sec) { + + printf("STATUS: ID=%u, RX=%u bytes/sec, " + "TX=%u bytes/sec, ERR=%u, RST=%u, DERR=%u\n", + (int)xfer_current_id, + (int)(stats.xfer_rx_bytes - + last_stat.xfer_rx_bytes), + (int)(stats.xfer_tx_bytes - + last_stat.xfer_tx_bytes), + (int)(stats.xfer_error), + (int)(stats.xfer_reset), + (int)(stats.data_error)); + + fflush(stdout); + + last_sec = sub_tv.tv_sec; + last_stat = stats; + } + timersub(&sub_tv, &ref_tv, &res_tv); + + if ((res_tv.tv_sec < 0) || (res_tv.tv_sec >= (int)p->duration)) + break; + + do_io_test(p, lun, lba_max, buffer, reference); + + if (libusb20_dev_check_connected(usb_pdev) != 0) { + printf("Device disconnected\n"); + break; + } + if (p->done) { + printf("Maximum number of errors exceeded\n"); + break; + } + } + + printf("\nTest done!\n"); + +fail: + if (buffer) + free(buffer); + if (reference) + free(reference); +} + +void +show_host_device_selection(uint8_t level, uint16_t *pvid, uint16_t *ppid) +{ + struct libusb20_backend *pbe; + struct libusb20_device *pdev; + struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; + + uint16_t vid[USB_DEVICES_MAX]; + uint16_t pid[USB_DEVICES_MAX]; + + int index; + int sel; + + const char *ptr; + +top: + pbe = libusb20_be_alloc_default(); + pdev = NULL; + index = 0; + + printf("\n[] Select USB device:\n"); + + while ((pdev = libusb20_be_device_foreach(pbe, pdev))) { + + if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST) + continue; + + if (index < USB_DEVICES_MAX) { + ddesc = libusb20_dev_get_device_desc(pdev); + ptr = libusb20_dev_get_desc(pdev); + printf("%s%d) %s\n", indent[level], index, ptr); + vid[index] = ddesc->idVendor; + pid[index] = ddesc->idProduct; + index++; + } else { + break; + } + } + + printf("%sr) Refresh device list\n", indent[level]); + printf("%sx) Return to previous menu\n", indent[level]); + + /* release data */ + libusb20_be_free(pbe); + + sel = get_integer(); + + if (sel == -2) + goto top; + + if ((sel < 0) || (sel >= index)) { + *pvid = 0; + *ppid = 0; + return; + } + *pvid = vid[sel]; + *ppid = pid[sel]; +} + +struct libusb20_device * +find_usb_device(uint16_t vid, uint16_t pid) +{ + struct libusb20_backend *pbe = libusb20_be_alloc_default(); + struct libusb20_device *pdev = NULL; + struct LIBUSB20_DEVICE_DESC_DECODED *ddesc; + + while ((pdev = libusb20_be_device_foreach(pbe, pdev))) { + + if (libusb20_dev_get_mode(pdev) != LIBUSB20_MODE_HOST) + continue; + + ddesc = libusb20_dev_get_device_desc(pdev); + + if ((vid == ddesc->idVendor) && + (pid == ddesc->idProduct)) { + libusb20_be_dequeue_device(pbe, pdev); + break; + } + } + + /* release data */ + libusb20_be_free(pbe); + + return (pdev); +} + +void +find_usb_endpoints(struct libusb20_device *pdev, uint8_t class, + uint8_t subclass, uint8_t protocol, uint8_t alt_setting, + uint8_t *pif, uint8_t *in_ep, uint8_t *out_ep, uint8_t next_if) +{ + struct libusb20_config *pcfg; + struct libusb20_interface *iface; + struct libusb20_endpoint *ep; + uint8_t x; + uint8_t y; + uint8_t z; + + *in_ep = 0; + *out_ep = 0; + *pif = 0; + + pcfg = libusb20_dev_alloc_config(pdev, + libusb20_dev_get_config_index(pdev)); + + if (pcfg == NULL) + return; + + for (x = 0; x != pcfg->num_interface; x++) { + + y = alt_setting; + + iface = (pcfg->interface + x); + + if ((iface->desc.bInterfaceClass == class) && + (iface->desc.bInterfaceSubClass == subclass || + subclass == 255) && + (iface->desc.bInterfaceProtocol == protocol || + protocol == 255)) { + + if (next_if) { + x++; + if (x == pcfg->num_interface) + break; + iface = (pcfg->interface + x); + } + *pif = x; + + for (z = 0; z != iface->num_endpoints; z++) { + ep = iface->endpoints + z; + + /* BULK only */ + if ((ep->desc.bmAttributes & 3) != 2) + continue; + + if (ep->desc.bEndpointAddress & 0x80) + *in_ep = ep->desc.bEndpointAddress; + else + *out_ep = ep->desc.bEndpointAddress; + } + break; + } + } + + free(pcfg); +} + +static void +exec_host_msc_test(struct usb_msc_params *p, uint16_t vid, uint16_t pid) +{ + struct libusb20_device *pdev; + + uint8_t in_ep; + uint8_t out_ep; + uint8_t iface; + + int error; + + memset(&stats, 0, sizeof(stats)); + + xfer_current_id = 0; + xfer_wrapper_sig = CBWSIGNATURE; + + pdev = find_usb_device(vid, pid); + if (pdev == NULL) { + printf("USB device not found\n"); + return; + } + find_usb_endpoints(pdev, 8, 6, 0x50, 0, &iface, &in_ep, &out_ep, 0); + + if ((in_ep == 0) || (out_ep == 0)) { + printf("Could not find USB endpoints\n"); + libusb20_dev_free(pdev); + return; + } + printf("Attaching to: %s @ iface %d\n", + libusb20_dev_get_desc(pdev), iface); + + if (libusb20_dev_open(pdev, 2)) { + printf("Could not open USB device\n"); + libusb20_dev_free(pdev); + return; + } + if (libusb20_dev_detach_kernel_driver(pdev, iface)) { + printf("WARNING: Could not detach kernel driver\n"); + } + xfer_in = libusb20_tr_get_pointer(pdev, 0); + error = libusb20_tr_open(xfer_in, 65536, 1, in_ep); + if (error) { + printf("Could not open USB endpoint %d\n", in_ep); + libusb20_dev_free(pdev); + return; + } + xfer_out = libusb20_tr_get_pointer(pdev, 1); + error = libusb20_tr_open(xfer_out, 65536, 1, out_ep); + if (error) { + printf("Could not open USB endpoint %d\n", out_ep); + libusb20_dev_free(pdev); + return; + } + usb_pdev = pdev; + usb_iface = iface; + + usb_msc_test(p); + + libusb20_dev_free(pdev); +} + +static void +set_defaults(struct usb_msc_params *p) +{ + memset(p, 0, sizeof(*p)); + + p->duration = 60; /* seconds */ + p->try_invalid_scsi_command = 1; + p->try_invalid_wrapper_block = 1; + p->try_last_lba = 1; + p->max_errors = -1; +} + +static const char * +get_io_mode(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_mode) { + case USB_MSC_IO_MODE_READ_ONLY: + return ("Read Only"); + case USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY: + return ("Write Once, Read Only"); + case USB_MSC_IO_MODE_WRITE_ONLY: + return ("Write Only"); + case USB_MSC_IO_MODE_READ_WRITE: + return ("Read and Write"); + default: + return ("Unknown"); + } +} + +static const char * +get_io_pattern(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_pattern) { + case USB_MSC_IO_PATTERN_FIXED: + return ("Fixed"); + case USB_MSC_IO_PATTERN_RANDOM: + return ("Random"); + case USB_MSC_IO_PATTERN_PRESERVE: + return ("Preserve"); + default: + return ("Unknown"); + } +} + +static const char * +get_io_size(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_size) { + case USB_MSC_IO_SIZE_RANDOM: + return ("Random"); + case USB_MSC_IO_SIZE_INCREASING: + return ("Increasing"); + case USB_MSC_IO_SIZE_FIXED_1BLK: + return ("Single block"); + case USB_MSC_IO_SIZE_FIXED_2BLK: + return ("2 blocks"); + case USB_MSC_IO_SIZE_FIXED_4BLK: + return ("4 blocks"); + case USB_MSC_IO_SIZE_FIXED_8BLK: + return ("8 blocks"); + case USB_MSC_IO_SIZE_FIXED_16BLK: + return ("16 blocks"); + case USB_MSC_IO_SIZE_FIXED_32BLK: + return ("32 blocks"); + case USB_MSC_IO_SIZE_FIXED_64BLK: + return ("64 blocks"); + case USB_MSC_IO_SIZE_FIXED_128BLK: + return ("128 blocks"); + case USB_MSC_IO_SIZE_FIXED_256BLK: + return ("256 blocks"); + case USB_MSC_IO_SIZE_FIXED_512BLK: + return ("512 blocks"); + case USB_MSC_IO_SIZE_FIXED_1024BLK: + return ("1024 blocks"); + default: + return ("Unknown"); + } +} + +static const char * +get_io_delay(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_delay) { + case USB_MSC_IO_DELAY_NONE: + return ("None"); + case USB_MSC_IO_DELAY_RANDOM_10MS: + return ("Random 10ms"); + case USB_MSC_IO_DELAY_RANDOM_100MS: + return ("Random 100ms"); + case USB_MSC_IO_DELAY_FIXED_10MS: + return ("Fixed 10ms"); + case USB_MSC_IO_DELAY_FIXED_100MS: + return ("Fixed 100ms"); + default: + return ("Unknown"); + } +} + +static const char * +get_io_offset(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_offset) { + case USB_MSC_IO_OFF_START_OF_DISK: + return ("Start Of Disk"); + case USB_MSC_IO_OFF_RANDOM: + return ("Random Offset"); + default: + return ("Unknown"); + } +} + +static const char * +get_io_area(const struct usb_msc_params *p) +{ + ; /* indent fix */ + switch (p->io_area) { + case USB_MSC_IO_AREA_COMPLETE: + return ("Complete Disk"); + case USB_MSC_IO_AREA_1MB: + return ("First MegaByte"); + case USB_MSC_IO_AREA_16MB: + return ("First 16 MegaBytes"); + case USB_MSC_IO_AREA_256MB: + return ("First 256 MegaBytes"); + default: + return ("Unknown"); + } +} + +void +show_host_msc_test(uint8_t level, uint16_t vid, + uint16_t pid, uint32_t duration) +{ + struct usb_msc_params params; + uint8_t retval; + + set_defaults(¶ms); + + params.duration = duration; + + while (1) { + + retval = usb_ts_show_menu(level, + "Mass Storage Test Parameters", + " 1) Toggle I/O mode: <%s>\n" + " 2) Toggle I/O size: <%s>\n" + " 3) Toggle I/O delay: <%s>\n" + " 4) Toggle I/O offset: <%s>\n" + " 5) Toggle I/O area: <%s>\n" + " 6) Toggle I/O pattern: <%s>\n" + " 7) Toggle try invalid SCSI command: <%s>\n" + " 8) Toggle try invalid wrapper block: <%s>\n" + " 9) Toggle try invalid MaxPacketSize: <%s>\n" + "10) Toggle try last Logical Block Address: <%s>\n" + "11) Toggle I/O lun: <%d>\n" + "12) Set maximum number of errors: <%d>\n" + "13) Set test duration: <%d> seconds\n" + "14) Toggle try aborted write transfer: <%s>\n" + "15) Toggle request sense on error: <%s>\n" + "16) Toggle try all LUN: <%s>\n" + "20) Reset parameters\n" + "30) Start test (VID=0x%04x, PID=0x%04x)\n" + "40) Select another device\n" + " x) Return to previous menu \n", + get_io_mode(¶ms), + get_io_size(¶ms), + get_io_delay(¶ms), + get_io_offset(¶ms), + get_io_area(¶ms), + get_io_pattern(¶ms), + (params.try_invalid_scsi_command ? "YES" : "NO"), + (params.try_invalid_wrapper_block ? "YES" : "NO"), + (params.try_invalid_max_packet_size ? "YES" : "NO"), + (params.try_last_lba ? "YES" : "NO"), + params.io_lun, + (int)params.max_errors, + (int)params.duration, + (params.try_abort_data_write ? "YES" : "NO"), + (params.try_sense_on_error ? "YES" : "NO"), + (params.try_all_lun ? "YES" : "NO"), + vid, pid); + switch (retval) { + case 0: + break; + case 1: + params.io_mode++; + params.io_mode %= USB_MSC_IO_MODE_MAX; + break; + case 2: + params.io_size++; + params.io_size %= USB_MSC_IO_SIZE_MAX; + break; + case 3: + params.io_delay++; + params.io_delay %= USB_MSC_IO_DELAY_MAX; + break; + case 4: + params.io_offset++; + params.io_offset %= USB_MSC_IO_OFF_MAX; + break; + case 5: + params.io_area++; + params.io_area %= USB_MSC_IO_AREA_MAX; + break; + case 6: + params.io_pattern++; + params.io_pattern %= USB_MSC_IO_PATTERN_MAX; + break; + case 7: + params.try_invalid_scsi_command ^= 1; + break; + case 8: + params.try_invalid_wrapper_block ^= 1; + break; + case 9: + params.try_invalid_max_packet_size ^= 1; + break; + case 10: + params.try_last_lba ^= 1; + break; + case 11: + params.io_lun++; + params.io_lun %= USB_MSC_IO_LUN_MAX; + break; + case 12: + params.max_errors = get_integer(); + break; + case 13: + params.duration = get_integer(); + break; + case 14: + params.try_abort_data_write ^= 1; + break; + case 15: + params.try_sense_on_error ^= 1; + break; + case 16: + params.try_all_lun ^= 1; + break; + case 20: + set_defaults(¶ms); + break; + case 30: + exec_host_msc_test(¶ms, vid, pid); + break; + case 40: + show_host_device_selection(level + 1, &vid, &pid); + break; + default: + return; + } + } +} diff --git a/tools/tools/usbtest/usb_msc_test.h b/tools/tools/usbtest/usb_msc_test.h new file mode 100644 index 0000000..3af7b08 --- /dev/null +++ b/tools/tools/usbtest/usb_msc_test.h @@ -0,0 +1,120 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + */ + +#ifndef _USB_MSC_TEST_H_ +#define _USB_MSC_TEST_H_ + +enum { + USB_MSC_IO_MODE_READ_ONLY, + USB_MSC_IO_MODE_WRITE_ONCE_READ_ONLY, + USB_MSC_IO_MODE_WRITE_ONLY, + USB_MSC_IO_MODE_READ_WRITE, + USB_MSC_IO_MODE_MAX, +}; + +enum { + USB_MSC_IO_PATTERN_FIXED, + USB_MSC_IO_PATTERN_RANDOM, + USB_MSC_IO_PATTERN_PRESERVE, + USB_MSC_IO_PATTERN_MAX, +}; + +enum { + USB_MSC_IO_SIZE_RANDOM, + USB_MSC_IO_SIZE_INCREASING, + USB_MSC_IO_SIZE_FIXED_1BLK, + USB_MSC_IO_SIZE_FIXED_2BLK, + USB_MSC_IO_SIZE_FIXED_4BLK, + USB_MSC_IO_SIZE_FIXED_8BLK, + USB_MSC_IO_SIZE_FIXED_16BLK, + USB_MSC_IO_SIZE_FIXED_32BLK, + USB_MSC_IO_SIZE_FIXED_64BLK, + USB_MSC_IO_SIZE_FIXED_128BLK, + USB_MSC_IO_SIZE_FIXED_256BLK, + USB_MSC_IO_SIZE_FIXED_512BLK, + USB_MSC_IO_SIZE_FIXED_1024BLK, + USB_MSC_IO_SIZE_MAX, +}; + +enum { + USB_MSC_IO_DELAY_NONE, + USB_MSC_IO_DELAY_RANDOM_10MS, + USB_MSC_IO_DELAY_RANDOM_100MS, + USB_MSC_IO_DELAY_FIXED_10MS, + USB_MSC_IO_DELAY_FIXED_100MS, + USB_MSC_IO_DELAY_MAX, +}; + +enum { + USB_MSC_IO_OFF_START_OF_DISK, + USB_MSC_IO_OFF_RANDOM, + USB_MSC_IO_OFF_MAX, +}; + +enum { + USB_MSC_IO_AREA_COMPLETE, + USB_MSC_IO_AREA_1MB, + USB_MSC_IO_AREA_16MB, + USB_MSC_IO_AREA_256MB, + USB_MSC_IO_AREA_MAX, +}; + +enum { + USB_MSC_IO_LUN_0, + USB_MSC_IO_LUN_1, + USB_MSC_IO_LUN_2, + USB_MSC_IO_LUN_3, + USB_MSC_IO_LUN_MAX, +}; + +struct usb_msc_params { + + uint32_t duration; + uint32_t max_errors; + + /* See "USB_MSC_XXX" enums */ + + uint8_t io_mode; + uint8_t io_size; + uint8_t io_delay; + uint8_t io_offset; + uint8_t io_area; + uint8_t io_pattern; + uint8_t io_lun; + + /* booleans */ + uint8_t try_invalid_scsi_command; + uint8_t try_invalid_wrapper_block; + uint8_t try_invalid_max_packet_size; + uint8_t try_last_lba; + uint8_t try_abort_data_write; + uint8_t try_sense_on_error; + uint8_t try_all_lun; + + uint8_t done; +}; + +#endif /* _USB_MSC_TEST_H_ */ diff --git a/tools/tools/usbtest/usbtest.c b/tools/tools/usbtest/usbtest.c new file mode 100644 index 0000000..725b9ea --- /dev/null +++ b/tools/tools/usbtest/usbtest.c @@ -0,0 +1,809 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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 <stdio.h> +#include <stdint.h> +#include <err.h> +#include <string.h> +#include <errno.h> +#include <stdarg.h> +#include <stdlib.h> + +#include <sys/types.h> +#include <sys/sysctl.h> + +#include <dev/usb/usb_ioctl.h> + +#include "usbtest.h" + +#include <g_keyboard.h> +#include <g_mouse.h> +#include <g_modem.h> +#include <g_audio.h> + +static uint8_t usb_ts_select[USB_TS_MAX_LEVELS]; + +const char *indent[USB_TS_MAX_LEVELS] = { + " ", + " ", + " ", + " ", + " ", + " ", + " ", + " ", +}; + +/* a perceptual white noise generator (after HPS' invention) */ + +int32_t +usb_ts_rand_noise(void) +{ + uint32_t temp; + const uint32_t prime = 0xFFFF1D; + static uint32_t noise_rem = 1; + + if (noise_rem & 1) { + noise_rem += prime; + } + noise_rem /= 2; + + temp = noise_rem; + + /* unsigned to signed conversion */ + + temp ^= 0x800000; + if (temp & 0x800000) { + temp |= (-0x800000); + } + return temp; +} + +uint8_t +usb_ts_show_menu(uint8_t level, const char *title, const char *fmt,...) +{ + va_list args; + uint8_t x; + uint8_t retval; + char *pstr; + char buf[16]; + char menu[80 * 20]; + + va_start(args, fmt); + vsnprintf(menu, sizeof(menu), fmt, args); + va_end(args); + + printf("["); + + for (x = 0; x != level; x++) { + if ((x + 1) == level) + printf("%d", usb_ts_select[x]); + else + printf("%d.", usb_ts_select[x]); + } + + printf("] - %s:\n\n", title); + + x = 1; + for (pstr = menu; *pstr; pstr++) { + if (x != 0) { + printf("%s", indent[level]); + x = 0; + } + printf("%c", *pstr); + + if (*pstr == '\n') + x = 1; + } + + printf("\n>"); + + if (fgets(buf, sizeof(buf), stdin) == NULL) + err(1, "Cannot read input"); + + if (buf[0] == 'x') + retval = 255; + else + retval = atoi(buf); + + usb_ts_select[level] = retval; + + return (retval); +} + +void +get_string(char *ptr, int size) +{ + printf("\nEnter string>"); + + if (fgets(ptr, size, stdin) == NULL) + err(1, "Cannot read input"); + + ptr[size - 1] = 0; + + size = strlen(ptr); + + /* strip trailing newline, if any */ + if (size == 0) + return; + else if (ptr[size - 1] == '\n') + ptr[size - 1] = 0; +} + +int +get_integer(void) +{ + char buf[32]; + + printf("\nEnter integer value>"); + + if (fgets(buf, sizeof(buf), stdin) == NULL) + err(1, "Cannot read input"); + + if (strcmp(buf, "x\n") == 0) + return (-1); + if (strcmp(buf, "r\n") == 0) + return (-2); + + return ((int)strtol(buf, 0, 0)); +} + +static void +set_template(int template) +{ + int error; + + error = sysctlbyname("hw.usb.template", NULL, NULL, + &template, sizeof(template)); + + if (error != 0) { + printf("WARNING: Could not set USB template " + "to %d (error=%d)\n", template, errno); + } +} + +static void +show_default_audio_select(uint8_t level) +{ + int error; + int retval; + int mode = 0; + int pattern_interval = 128; + int throughput = 0; + size_t len; + char pattern[G_AUDIO_MAX_STRLEN] = {"0123456789abcdef"}; + + set_template(USB_TEMP_AUDIO); + + while (1) { + + error = sysctlbyname("hw.usb.g_audio.mode", NULL, NULL, + &mode, sizeof(mode)); + + if (error != 0) { + printf("WARNING: Could not set audio mode " + "to %d (error=%d)\n", mode, errno); + } + error = sysctlbyname("hw.usb.g_audio.pattern_interval", NULL, NULL, + &pattern_interval, sizeof(pattern_interval)); + + if (error != 0) { + printf("WARNING: Could not set pattern interval " + "to %d (error=%d)\n", pattern_interval, errno); + } + len = sizeof(throughput); + + error = sysctlbyname("hw.usb.g_audio.throughput", + &throughput, &len, 0, 0); + + if (error != 0) { + printf("WARNING: Could not get throughput " + "(error=%d)\n", errno); + } + error = sysctlbyname("hw.usb.g_audio.pattern", NULL, NULL, + &pattern, strlen(pattern)); + + if (error != 0) { + printf("WARNING: Could not set audio pattern " + "to '%s' (error=%d)\n", pattern, errno); + } + retval = usb_ts_show_menu(level, "Default Audio Settings", + "1) Set Silent mode %s\n" + "2) Set Dump mode %s\n" + "3) Set Loop mode %s\n" + "4) Set Pattern mode %s\n" + "5) Change DTMF pattern: '%s'\n" + "6) Change pattern advance interval: %d ms\n" + "x) Return to previous menu\n" + "s: Ready for enumeration\n" + "t: Throughput: %d bytes/second\n", + (mode == G_AUDIO_MODE_SILENT) ? "(selected)" : "", + (mode == G_AUDIO_MODE_DUMP) ? "(selected)" : "", + (mode == G_AUDIO_MODE_LOOP) ? "(selected)" : "", + (mode == G_AUDIO_MODE_PATTERN) ? "(selected)" : "", + pattern, pattern_interval, throughput); + + switch (retval) { + case 0: + break; + case 1: + mode = G_AUDIO_MODE_SILENT; + break; + case 2: + mode = G_AUDIO_MODE_DUMP; + break; + case 3: + mode = G_AUDIO_MODE_LOOP; + break; + case 4: + mode = G_AUDIO_MODE_PATTERN; + break; + case 5: + get_string(pattern, sizeof(pattern)); + break; + case 6: + pattern_interval = get_integer(); + break; + default: + return; + } + } +} + +static void +show_device_audio_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Audio Device Model", + "1) Generic Audio Device\n" + "x) Return to previous menu\n"); + + switch (retval) { + case 0: + break; + case 1: + show_default_audio_select(level + 1); + break; + default: + return; + } + } +} + +static void +show_device_msc_select(uint8_t level) +{ + set_template(USB_TEMP_MSC); +} + +static void +show_device_ethernet_select(uint8_t level) +{ + set_template(USB_TEMP_CDCE); +} + +static void +show_default_keyboard_select(uint8_t level) +{ + int error; + int retval; + int mode = 0; + int interval = 1023; + char pattern[G_KEYBOARD_MAX_STRLEN] = {"abcdefpattern"}; + + set_template(USB_TEMP_KBD); + + while (1) { + + error = sysctlbyname("hw.usb.g_keyboard.mode", NULL, NULL, + &mode, sizeof(mode)); + + if (error != 0) { + printf("WARNING: Could not set keyboard mode " + " to %d (error=%d) \n", mode, errno); + } + error = sysctlbyname("hw.usb.g_keyboard.key_press_interval", NULL, NULL, + &interval, sizeof(interval)); + + if (error != 0) { + printf("WARNING: Could not set key press interval " + "to %d (error=%d)\n", interval, errno); + } + error = sysctlbyname("hw.usb.g_keyboard.key_press_pattern", NULL, NULL, + &pattern, strlen(pattern)); + + if (error != 0) { + printf("WARNING: Could not set key pattern " + "to '%s' (error=%d)\n", pattern, errno); + } + retval = usb_ts_show_menu(level, "Default Keyboard Settings", + "1) Set silent mode %s\n" + "2) Set pattern mode %s\n" + "3) Change pattern: '%s'\n" + "4) Change key press interval: %d ms\n" + "x) Return to previous menu\n" + "s: Ready for enumeration\n", + (mode == G_KEYBOARD_MODE_SILENT) ? "(selected)" : "", + (mode == G_KEYBOARD_MODE_PATTERN) ? "(selected)" : "", + pattern, interval); + + switch (retval) { + case 0: + break; + case 1: + mode = G_KEYBOARD_MODE_SILENT; + break; + case 2: + mode = G_KEYBOARD_MODE_PATTERN; + break; + case 3: + get_string(pattern, sizeof(pattern)); + break; + case 4: + interval = get_integer(); + break; + default: + return; + } + } +} + +static void +show_device_keyboard_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Keyboard Model", + "1) Generic Keyboard \n" + "x) Return to previous menu \n"); + + switch (retval) { + case 0: + break; + case 1: + show_default_keyboard_select(level + 1); + break; + default: + return; + } + } +} + +static void +show_default_mouse_select(uint8_t level) +{ + int error; + int retval; + int mode = 0; + int cursor_interval = 128; + int cursor_radius = 75; + int button_interval = 0; + + set_template(USB_TEMP_MOUSE); + + while (1) { + + error = sysctlbyname("hw.usb.g_mouse.mode", NULL, NULL, + &mode, sizeof(mode)); + + if (error != 0) { + printf("WARNING: Could not set mouse mode " + "to %d (error=%d)\n", mode, errno); + } + error = sysctlbyname("hw.usb.g_mouse.cursor_update_interval", NULL, NULL, + &cursor_interval, sizeof(cursor_interval)); + + if (error != 0) { + printf("WARNING: Could not set cursor update interval " + "to %d (error=%d)\n", cursor_interval, errno); + } + error = sysctlbyname("hw.usb.g_mouse.button_press_interval", NULL, NULL, + &button_interval, sizeof(button_interval)); + + if (error != 0) { + printf("WARNING: Could not set button press interval " + "to %d (error=%d)\n", button_interval, errno); + } + error = sysctlbyname("hw.usb.g_mouse.cursor_radius", NULL, NULL, + &cursor_radius, sizeof(cursor_radius)); + + if (error != 0) { + printf("WARNING: Could not set cursor radius " + "to %d (error=%d)\n", cursor_radius, errno); + } + retval = usb_ts_show_menu(level, "Default Mouse Settings", + "1) Set Silent mode %s\n" + "2) Set Circle mode %s\n" + "3) Set Square mode %s\n" + "4) Set Spiral mode %s\n" + "5) Change cursor radius: %d pixels\n" + "6) Change cursor update interval: %d ms\n" + "7) Change button[0] press interval: %d ms\n" + "x) Return to previous menu\n" + "s: Ready for enumeration\n", + (mode == G_MOUSE_MODE_SILENT) ? "(selected)" : "", + (mode == G_MOUSE_MODE_CIRCLE) ? "(selected)" : "", + (mode == G_MOUSE_MODE_BOX) ? "(selected)" : "", + (mode == G_MOUSE_MODE_SPIRAL) ? "(selected)" : "", + cursor_radius, cursor_interval, button_interval); + + switch (retval) { + case 0: + break; + case 1: + mode = G_MOUSE_MODE_SILENT; + break; + case 2: + mode = G_MOUSE_MODE_CIRCLE; + break; + case 3: + mode = G_MOUSE_MODE_BOX; + break; + case 4: + mode = G_MOUSE_MODE_SPIRAL; + break; + case 5: + cursor_radius = get_integer(); + break; + case 6: + cursor_interval = get_integer(); + break; + case 7: + button_interval = get_integer(); + break; + default: + return; + } + } +} + +static void +show_device_mouse_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Mouse Model", + "1) Generic Mouse\n" + "x) Return to previous menu\n"); + + switch (retval) { + case 0: + break; + case 1: + show_default_mouse_select(level + 1); + break; + default: + return; + } + } +} + +static void +show_device_mtp_select(uint8_t level) +{ + set_template(USB_TEMP_MTP); +} + +static void +show_default_modem_select(uint8_t level) +{ + int error; + int retval; + int mode = 0; + int pattern_interval = 128; + int throughput = 0; + size_t len; + char pattern[G_MODEM_MAX_STRLEN] = {"abcdefpattern"}; + + set_template(USB_TEMP_MODEM); + + while (1) { + + error = sysctlbyname("hw.usb.g_modem.mode", NULL, NULL, + &mode, sizeof(mode)); + + if (error != 0) { + printf("WARNING: Could not set modem mode " + "to %d (error=%d)\n", mode, errno); + } + error = sysctlbyname("hw.usb.g_modem.pattern_interval", NULL, NULL, + &pattern_interval, sizeof(pattern_interval)); + + if (error != 0) { + printf("WARNING: Could not set pattern interval " + "to %d (error=%d)\n", pattern_interval, errno); + } + len = sizeof(throughput); + + error = sysctlbyname("hw.usb.g_modem.throughput", + &throughput, &len, 0, 0); + + if (error != 0) { + printf("WARNING: Could not get throughput " + "(error=%d)\n", errno); + } + error = sysctlbyname("hw.usb.g_modem.pattern", NULL, NULL, + &pattern, strlen(pattern)); + + if (error != 0) { + printf("WARNING: Could not set modem pattern " + "to '%s' (error=%d)\n", pattern, errno); + } + retval = usb_ts_show_menu(level, "Default Modem Settings", + "1) Set Silent mode %s\n" + "2) Set Dump mode %s\n" + "3) Set Loop mode %s\n" + "4) Set Pattern mode %s\n" + "5) Change test pattern: '%s'\n" + "6) Change data transmit interval: %d ms\n" + "x) Return to previous menu\n" + "s: Ready for enumeration\n" + "t: Throughput: %d bytes/second\n", + (mode == G_MODEM_MODE_SILENT) ? "(selected)" : "", + (mode == G_MODEM_MODE_DUMP) ? "(selected)" : "", + (mode == G_MODEM_MODE_LOOP) ? "(selected)" : "", + (mode == G_MODEM_MODE_PATTERN) ? "(selected)" : "", + pattern, pattern_interval, throughput); + + switch (retval) { + case 0: + break; + case 1: + mode = G_MODEM_MODE_SILENT; + break; + case 2: + mode = G_MODEM_MODE_DUMP; + break; + case 3: + mode = G_MODEM_MODE_LOOP; + break; + case 4: + mode = G_MODEM_MODE_PATTERN; + break; + case 5: + get_string(pattern, sizeof(pattern)); + break; + case 6: + pattern_interval = get_integer(); + break; + default: + return; + } + } +} + +static void +show_device_modem_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Modem Model", + "1) Generic Modem\n" + "x) Return to previous menu\n"); + + switch (retval) { + case 0: + break; + case 1: + show_default_modem_select(level + 1); + break; + default: + return; + } + } +} + +static void +show_device_generic_select(uint8_t level) +{ +} + +static void +show_device_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Device Mode Test Group", + "1) Audio (UAUDIO)\n" + "2) Mass Storage (MSC)\n" + "3) Ethernet (CDCE)\n" + "4) Keyboard Input Device (UKBD)\n" + "5) Mouse Input Device (UMS)\n" + "6) Message Transfer Protocol (MTP)\n" + "7) Modem (CDC)\n" + "8) Generic Endpoint Loopback (GENERIC)\n" + "x) Return to previous menu\n"); + + switch (retval) { + case 0: + break; + case 1: + show_device_audio_select(level + 1); + break; + case 2: + show_device_msc_select(level + 1); + break; + case 3: + show_device_ethernet_select(level + 1); + break; + case 4: + show_device_keyboard_select(level + 1); + break; + case 5: + show_device_mouse_select(level + 1); + break; + case 6: + show_device_mtp_select(level + 1); + break; + case 7: + show_device_modem_select(level + 1); + break; + case 8: + show_device_generic_select(level + 1); + break; + default: + return; + } + } +} + +static void +show_host_select(uint8_t level) +{ + int force_fs = 0; + int error; + uint32_t duration = 60; + + uint16_t dev_vid = 0; + uint16_t dev_pid = 0; + uint8_t retval; + + while (1) { + + error = sysctlbyname("hw.usb.ehci.no_hs", NULL, NULL, + &force_fs, sizeof(force_fs)); + + if (error != 0) { + printf("WARNING: Could not set non-FS mode " + "to %d (error=%d)\n", force_fs, errno); + } + retval = usb_ts_show_menu(level, "Select Host Mode Test (via LibUSB)", + " 1) Select USB device (VID=0x%04x, PID=0x%04x)\n" + " 2) Manually enter USB vendor and product ID\n" + " 3) Force FULL speed operation: <%s>\n" + " 4) Mass Storage (UMASS)\n" + " 5) Modem (UMODEM)\n" + "10) Start String Descriptor Test\n" + "11) Start Port Reset Test\n" + "12) Start Set Config Test\n" + "13) Start Get Descriptor Test\n" + "14) Start Suspend and Resume Test\n" + "15) Start Set and Clear Endpoint Stall Test\n" + "16) Start Set Alternate Interface Setting Test\n" + "17) Start Invalid Control Request Test\n" + "30) Duration: <%d> seconds\n" + "x) Return to previous menu\n", + dev_vid, dev_pid, + force_fs ? "YES" : "NO", + (int)duration); + + switch (retval) { + case 0: + break; + case 1: + show_host_device_selection(level + 1, &dev_vid, &dev_pid); + break; + case 2: + dev_vid = get_integer() & 0xFFFF; + dev_pid = get_integer() & 0xFFFF; + break; + case 3: + force_fs ^= 1; + break; + case 4: + show_host_msc_test(level + 1, dev_vid, dev_pid, duration); + break; + case 5: + show_host_modem_test(level + 1, dev_vid, dev_pid, duration); + break; + case 10: + usb_get_string_desc_test(dev_vid, dev_pid); + break; + case 11: + usb_port_reset_test(dev_vid, dev_pid, duration); + break; + case 12: + usb_set_config_test(dev_vid, dev_pid, duration); + break; + case 13: + usb_get_descriptor_test(dev_vid, dev_pid, duration); + break; + case 14: + usb_suspend_resume_test(dev_vid, dev_pid, duration); + break; + case 15: + usb_set_and_clear_stall_test(dev_vid, dev_pid); + break; + case 16: + usb_set_alt_interface_test(dev_vid, dev_pid); + break; + case 17: + usb_control_ep_error_test(dev_vid, dev_pid); + break; + case 30: + duration = get_integer(); + break; + default: + return; + } + } +} + +static void +show_mode_select(uint8_t level) +{ + uint8_t retval; + + while (1) { + + retval = usb_ts_show_menu(level, "Select Computer Mode", + "1) This computer is Running the Device Side\n" + "2) This computer is Running the Host Side\n" + "x) Return to previous menu\n"); + + switch (retval) { + case 0: + break; + case 1: + show_device_select(level + 1); + break; + case 2: + show_host_select(level + 1); + break; + default: + return; + } + } +} + +int +main(int argc, char **argv) +{ + show_mode_select(1); + + return (0); +} diff --git a/tools/tools/usbtest/usbtest.h b/tools/tools/usbtest/usbtest.h new file mode 100644 index 0000000..3d6643c --- /dev/null +++ b/tools/tools/usbtest/usbtest.h @@ -0,0 +1,62 @@ +/* $FreeBSD$ */ +/*- + * Copyright (c) 2010 Hans Petter Selasky. 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. + */ + +#ifndef _USBTEST_H_ +#define _USBTEST_H_ + +#define USB_DEVICES_MAX 128 +#define USB_TS_MAX_LEVELS 8 + +struct libusb20_device; + +struct bps { + uint32_t bytes; + time_t time; +}; + +extern void usb_get_string_desc_test(uint16_t, uint16_t); +extern void usb_port_reset_test(uint16_t, uint16_t, uint32_t); +extern void usb_set_config_test(uint16_t, uint16_t, uint32_t); +extern void usb_get_descriptor_test(uint16_t, uint16_t, uint32_t); +extern void usb_control_ep_error_test(uint16_t, uint16_t); +extern void usb_set_and_clear_stall_test(uint16_t, uint16_t); +extern void usb_set_alt_interface_test(uint16_t, uint16_t); + +extern void usb_suspend_resume_test(uint16_t, uint16_t, uint32_t); +extern void do_bps(const char *, struct bps *, uint32_t len); +extern const char *indent[USB_TS_MAX_LEVELS]; +extern void show_host_msc_test(uint8_t, uint16_t, uint16_t, uint32_t); +extern void show_host_modem_test(uint8_t, uint16_t, uint16_t, uint32_t); +extern void show_host_device_selection(uint8_t, uint16_t *, uint16_t *); +extern struct libusb20_device *find_usb_device(uint16_t, uint16_t); +extern void find_usb_endpoints(struct libusb20_device *, uint8_t, uint8_t, + uint8_t, uint8_t, uint8_t *, uint8_t *, uint8_t *, uint8_t); +extern void get_string(char *, int); +extern int get_integer(void); +extern uint8_t usb_ts_show_menu(uint8_t, const char *, const char *,...); +extern int32_t usb_ts_rand_noise(void); + +#endif /* _USBTEST_H_ */ diff --git a/tools/tools/zfsboottest/Makefile b/tools/tools/zfsboottest/Makefile index c0c7d92..a04c78f 100644 --- a/tools/tools/zfsboottest/Makefile +++ b/tools/tools/zfsboottest/Makefile @@ -15,8 +15,7 @@ CFLAGS= -O1 \ -I${.CURDIR}/../../../sys/cddl/boot/zfs \ -I. \ -fdiagnostics-show-option \ - -W -Wextra -Wno-sign-compare -Wno-unused-parameter \ - -Werror + -W -Wextra -Wno-sign-compare -Wno-unused-parameter LDFLAGS+=-lmd .if ${MACHINE_CPUARCH} == "amd64" diff --git a/tools/tools/zfsboottest/zfsboottest.c b/tools/tools/zfsboottest/zfsboottest.c index 3058046..29e9a48 100644 --- a/tools/tools/zfsboottest/zfsboottest.c +++ b/tools/tools/zfsboottest/zfsboottest.c @@ -52,6 +52,7 @@ pager_output(const char *line) #define ZFS_TEST #define printf(...) fprintf(stderr, __VA_ARGS__) +#include "libzfs.h" #include "zfsimpl.c" #undef printf @@ -134,7 +135,6 @@ main(int argc, char** argv) close(fd[i - 1]); } } - spa_all_status(); spa = STAILQ_FIRST(&zfs_pools); if (spa == NULL) { @@ -147,7 +147,10 @@ main(int argc, char** argv) exit(1); } + spa_all_status(); + #if 0 + uint64_t rootobj; if (zfs_get_root(spa, &rootobj)) { fprintf(stderr, "can't get root\n"); exit(1); @@ -158,8 +161,8 @@ main(int argc, char** argv) if (zfs_mount(spa, 0, &zfsmnt)) { fprintf(stderr, "can't mount\n"); exit(1); - } #endif + } printf("\n"); for (++i, failures = 0; i < argc; i++) { diff --git a/tools/tools/zfsboottest/zfsboottest.sh b/tools/tools/zfsboottest/zfsboottest.sh index 1707e3f..1aea755 100755 --- a/tools/tools/zfsboottest/zfsboottest.sh +++ b/tools/tools/zfsboottest/zfsboottest.sh @@ -54,11 +54,6 @@ bootfs=`zpool get bootfs "${pool}" | tail -1 | awk '{print $3}'` if [ "${bootfs}" = "-" ]; then bootfs="${pool}" fi -# Dataset's mountpoint property should be set to 'legacy'. -if [ "`zfs get -H -o value mountpoint ${bootfs}`" != "legacy" ]; then - echo "The \"mountpoint\" property of dataset \"${bootfs}\" should be set to \"legacy\"." >&2 - exit 1 -fi mountpoint=`df -t zfs "${bootfs}" 2>/dev/null | tail -1 | awk '{print $6}'` if [ -z "${mountpoint}" ]; then echo "The \"${bootfs}\" dataset is not mounted." >&2 @@ -68,19 +63,6 @@ if [ ! -d "${mountpoint}${startdir}" ]; then echo "The \"${mountpoint}${startdir}\" directory doesn't exist." >&2 exit 1 fi -# To be able to mount root ZFS file system we need either /etc/fstab entry -# or vfs.root.mountfrom variable set in /boot/loader.conf. -egrep -q '^'"${bootfs}"'[[:space:]]+/[[:space:]]+zfs[[:space:]]+' "${mountpoint}/etc/fstab" 2>/dev/null -if [ $? -ne 0 ]; then - egrep -q 'vfs.root.mountfrom="?'"zfs:${bootfs}"'"?[[:space:]]*$' "${mountpoint}/boot/loader.conf" 2>/dev/null - if [ $? -ne 0 ]; then - echo "To be able to boot from \"${bootfs}\", you need to declare" >&2 - echo "\"${bootfs}\" as being root file system in ${mountpoint}/etc/fstab" >&2 - echo "or add \"vfs.root.mountfrom\" variable set to \"zfs:${bootfs}\" to" >&2 - echo "${mountpoint}/boot/loader.conf." >&2 - exit 1 - fi -fi vdevs="" for vdev in `zpool status "${pool}" | grep ONLINE | awk '{print $1}'`; do vdev="/dev/${vdev#/dev/}" |