summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.todo1
-rwxr-xr-xbuilder.py8
-rwxr-xr-xfind_licenses_and_unused.sh121
-rw-r--r--freebsd/COPYRIGHT126
-rw-r--r--freebsd/contrib/expat/COPYING21
-rw-r--r--freebsd/contrib/libpcap/LICENSE19
-rw-r--r--freebsd/contrib/libxo/LICENSE23
-rw-r--r--freebsd/contrib/tcpdump/LICENSE19
-rw-r--r--freebsd/contrib/tcpdump/tcpdump.c95
-rw-r--r--freebsd/contrib/wpa/COPYING22
-rw-r--r--freebsd/crypto/openssl/LICENSE125
-rw-r--r--freebsd/sbin/pfctl/pfctl_parser.c10
-rw-r--r--freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h1
-rw-r--r--freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h2
-rw-r--r--freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_parser-data.h1
-rw-r--r--freebsd/sbin/ping6/ping6.c11
-rw-r--r--freebsd/sys/contrib/libsodium/LICENSE18
-rw-r--r--freebsd/sys/dev/dc/if_dc.c7
-rw-r--r--freebsd/sys/dev/dc/if_dcreg.h7
-rw-r--r--freebsd/sys/dev/e1000/LICENSE31
-rw-r--r--freebsd/sys/dev/usb/controller/ehci_pci.c592
-rw-r--r--freebsd/sys/dev/usb/usb_pci.h43
-rw-r--r--freebsd/sys/i386/include/machine/intr_machdep.h6
-rw-r--r--freebsd/usr.sbin/ifmcstat/ifmcstat.c1295
-rw-r--r--freebsd/usr.sbin/ifmcstat/printb.c75
-rw-r--r--freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-data.h4
-rw-r--r--freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-ifmcstat-data.h7
-rw-r--r--freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-namespace.h5
-rw-r--r--freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-printb-data.h4
-rw-r--r--ipsec-tools/src/libipsec/pfkey.c7
-rw-r--r--ipsec-tools/src/racoon/rtems-bsd-racoon-session-data.h6
-rw-r--r--ipsec-tools/src/racoon/session.c47
-rw-r--r--libbsd.py56
-rw-r--r--rtemsbsd/include/bsp/nexus-devices.h8
-rw-r--r--rtemsbsd/include/machine/bus.h387
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-commands.h2
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-nexus-bus.h17
-rw-r--r--rtemsbsd/include/machine/rtems-bsd-program.h6
-rw-r--r--rtemsbsd/include/rtems/netcmds-config.h4
-rw-r--r--rtemsbsd/nfsclient/nfs.c89
-rw-r--r--rtemsbsd/powerpc/include/machine/legacyvar.h2
-rw-r--r--rtemsbsd/powerpc/include/machine/pci_cfgreg.h2
-rw-r--r--rtemsbsd/rtems/program-internal.h7
-rw-r--r--rtemsbsd/rtems/rtems-bsd-shell-ifmcstat.c36
-rw-r--r--rtemsbsd/rtems/rtems-kernel-bus-dma.c5
-rw-r--r--rtemsbsd/rtems/rtems-kernel-nexus.c52
-rw-r--r--rtemsbsd/rtems/rtems-program.c51
-rw-r--r--rtemsbsd/sys/dev/atsam/if_atsam.c1170
-rw-r--r--rtemsbsd/sys/dev/nvd/nvd.c37
-rw-r--r--rtemsbsd/sys/net/if_ppp.c11
-rw-r--r--rtemsbsd/sys/net/if_pppvar.h1
-rw-r--r--rtemsbsd/sys/net/ppp_tty.c32
-rw-r--r--testsuite/mcast01/test_main.c286
-rw-r--r--testsuite/media01/test_main.c3
-rw-r--r--testsuite/netshell01/test_main.c2
-rw-r--r--testsuite/pf02/test_main.c7
-rw-r--r--testsuite/ppp01/test_main.c2
-rw-r--r--testsuite/tcpdump01/test_main.c292
-rw-r--r--testsuite/telnetd01/test_main.c2
-rw-r--r--testsuite/zerocopy01/test_main.c2
-rw-r--r--waf_libbsd.py27
61 files changed, 4561 insertions, 796 deletions
diff --git a/Makefile.todo b/Makefile.todo
index a05716ef..36951c55 100644
--- a/Makefile.todo
+++ b/Makefile.todo
@@ -86,6 +86,7 @@ program-header:
cd freebsd/tools/tools/net80211/wlanstats && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/tools/tools/net80211/wlanstats/*.o -p wlanstats
cd freebsd/usr.bin/netstat && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/usr.bin/netstat/*.o -p netstat
cd freebsd/usr.sbin/arp && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/usr.sbin/arp/*.o -p arp
+ cd freebsd/usr.sbin/ifmcstat && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/freebsd/usr.sbin/ifmcstat/*.o -p ifmcstat
cd ipsec-tools/src/racoon && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/ipsec-tools/src/racoon/*.o -p racoon
cd ipsec-tools/src/setkey && $(BASE)/userspace-header-gen.py $(BUILD_BSP)/ipsec-tools/src/setkey/*.o -p setkey
diff --git a/builder.py b/builder.py
index f5fe2afc..0eda461f 100755
--- a/builder.py
+++ b/builder.py
@@ -202,6 +202,9 @@ def revertFixLocalIncludes(data):
data = re.sub('#include <rtems/bsd/local/([^>]*)>', '#include "\\1"', data)
return data
+def assertNothing(path):
+ pass
+
def assertHeaderFile(path):
if path[-2] != '.' or path[-1] != 'h':
print("*** " + path + " does not end in .h")
@@ -690,6 +693,11 @@ class Module(object):
reverseConverter, buildSystemComposer)]
return files
+ def addPlainTextFile(self, files):
+ self.files += self.addFiles(files,
+ FreeBSDPathComposer(), Converter(),
+ Converter(), assertNothing)
+
def addKernelSpaceHeaderFiles(self, files):
self.files += self.addFiles(files,
FreeBSDPathComposer(), FromFreeBSDToRTEMSHeaderConverter(),
diff --git a/find_licenses_and_unused.sh b/find_licenses_and_unused.sh
new file mode 100755
index 00000000..ee15f652
--- /dev/null
+++ b/find_licenses_and_unused.sh
@@ -0,0 +1,121 @@
+#!/bin/bash
+
+#
+# Copyright (c) 2018 embedded brains GmbH. All rights reserved.
+#
+# embedded brains GmbH
+# Dornierstr. 4
+# 82178 Puchheim
+# Germany
+# <rtems@embedded-brains.de>
+#
+# 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.
+#
+
+# exit on wrong command and undefined variable
+set -e
+set -u
+set -o pipefail
+
+SCRIPTNAME=$0
+TARGET="freebsd/"
+SOURCE="freebsd-org/"
+LIST="libbsd.py"
+FORCE=0
+
+printhelp () {
+ echo ""
+ echo "Call: ${SCRIPTNAME} <options>"
+ echo "1. Find LICENSE files for each file in \"${TARGET}\" if the"
+ echo " license file is not in ${LIST}."
+ echo "2. Find all files in \"${TARGET}\" that are not in \"${LIST}\"."
+ echo " Note: This function currently prints a lot of generated files too."
+ echo "Reccomended usage:"
+ echo "./${SCRIPTNAME} | sort | uniq"
+ echo ""
+ echo "The following parameters are optional:"
+ echo " -h Print this help and exit the script."
+ echo " -f Force printing all license files."
+ echo " -v Be more verbose. Can be used multiple times."
+ exit 0
+}
+
+while getopts "hfv" OPTION
+do
+ case ${OPTION} in
+ h) printhelp ;;
+ f) FORCE=1 ;;
+ \?) echo "Unknown option \"-${OPTARG}\"."
+ exit 1 ;;
+ :) echo "Option \"-${OPTARG}\" needs an argument."; exit 1 ;;
+ esac
+done
+shift $((${OPTIND} - 1))
+
+checkfile () {
+ local FILE="$1"
+ local FILE_WITHOUT_PATH=${FILE#"$TARGET"}
+ local LICENSE=""
+
+ grep "${FILE_WITHOUT_PATH}" "${LIST}" > /dev/null || \
+ echo "File not in ${LIST}: ${FILE_WITHOUT_PATH}"
+
+ local DIR="${SOURCE}`dirname ${FILE_WITHOUT_PATH}`"
+ while [ "$DIR" != "." ]
+ do
+ local MAYBELICENSE="${DIR}/LICENSE*"
+ if [ -e ${MAYBELICENSE} ]
+ then
+ LICENSE=`ls ${MAYBELICENSE}`
+ break
+ fi
+ local MAYBELICENSE="${DIR}/COPY*"
+ if [ -e ${MAYBELICENSE} ]
+ then
+ LICENSE=`ls ${MAYBELICENSE}`
+ break
+ fi
+ DIR="`dirname ${DIR}`"
+ done
+
+ if [ "${LICENSE}" != "" ]
+ then
+ local LICENSE_WITHOUT_PATH=${LICENSE#"$SOURCE"}
+ if grep "${LICENSE_WITHOUT_PATH}" "${LIST}" > /dev/null
+ then
+ if [ ${FORCE} -ne 0 ]
+ then
+ echo "License file found: ${LICENSE}"
+ fi
+ else
+ echo "New license file found: ${LICENSE}"
+ fi
+ fi
+}
+
+export -f checkfile
+export TARGET
+export SOURCE
+export LIST
+export FORCE
+
+find ${TARGET} -name "*\.[ch]" -exec bash -c 'checkfile "$0"' {} \;
diff --git a/freebsd/COPYRIGHT b/freebsd/COPYRIGHT
new file mode 100644
index 00000000..4a40a9f3
--- /dev/null
+++ b/freebsd/COPYRIGHT
@@ -0,0 +1,126 @@
+# $FreeBSD$
+# @(#)COPYRIGHT 8.2 (Berkeley) 3/21/94
+
+The compilation of software known as FreeBSD is distributed under the
+following terms:
+
+Copyright (c) 1992-2020 The FreeBSD Project.
+
+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.
+
+The 4.4BSD and 4.4BSD-Lite software is distributed under the following
+terms:
+
+All of the documentation and software included in the 4.4BSD and 4.4BSD-Lite
+Releases is copyrighted by The Regents of the University of California.
+
+Copyright 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
+ The Regents of the University of California. All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+3. All advertising materials mentioning features or use of this software
+ must display the following acknowledgement:
+This product includes software developed by the University of
+California, Berkeley and its contributors.
+4. Neither the name of the University nor the names of its contributors
+ may be used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+SUCH DAMAGE.
+
+The Institute of Electrical and Electronics Engineers and the American
+National Standards Committee X3, on Information Processing Systems have
+given us permission to reprint portions of their documentation.
+
+In the following statement, the phrase ``this text'' refers to portions
+of the system documentation.
+
+Portions of this text are reprinted and reproduced in electronic form in
+the second BSD Networking Software Release, from IEEE Std 1003.1-1988, IEEE
+Standard Portable Operating System Interface for Computer Environments
+(POSIX), copyright C 1988 by the Institute of Electrical and Electronics
+Engineers, Inc. In the event of any discrepancy between these versions
+and the original IEEE Standard, the original IEEE Standard is the referee
+document.
+
+In the following statement, the phrase ``This material'' refers to portions
+of the system documentation.
+
+This material is reproduced with permission from American National
+Standards Committee X3, on Information Processing Systems. Computer and
+Business Equipment Manufacturers Association (CBEMA), 311 First St., NW,
+Suite 500, Washington, DC 20001-2178. The developmental work of
+Programming Language C was completed by the X3J11 Technical Committee.
+
+The views and conclusions contained in the software and documentation are
+those of the authors and should not be interpreted as representing official
+policies, either expressed or implied, of the Regents of the University
+of California.
+
+
+NOTE: The copyright of UC Berkeley's Berkeley Software Distribution ("BSD")
+source has been updated. The copyright addendum may be found at
+ftp://ftp.cs.berkeley.edu/pub/4bsd/README.Impt.License.Change and is
+included below.
+
+July 22, 1999
+
+To All Licensees, Distributors of Any Version of BSD:
+
+As you know, certain of the Berkeley Software Distribution ("BSD") source
+code files require that further distributions of products containing all or
+portions of the software, acknowledge within their advertising materials
+that such products contain software developed by UC Berkeley and its
+contributors.
+
+Specifically, the provision reads:
+
+" * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * This product includes software developed by the University of
+ * California, Berkeley and its contributors."
+
+Effective immediately, licensees and distributors are no longer required to
+include the acknowledgement within advertising materials. Accordingly, the
+foregoing paragraph of those BSD Unix files containing it is hereby deleted
+in its entirety.
+
+William Hoskins
+Director, Office of Technology Licensing
+University of California, Berkeley
diff --git a/freebsd/contrib/expat/COPYING b/freebsd/contrib/expat/COPYING
new file mode 100644
index 00000000..8d288f0f
--- /dev/null
+++ b/freebsd/contrib/expat/COPYING
@@ -0,0 +1,21 @@
+Copyright (c) 1998-2000 Thai Open Source Software Center Ltd and Clark Cooper
+Copyright (c) 2001-2017 Expat maintainers
+
+Permission is hereby granted, free of charge, to any person obtaining
+a copy of this software and associated documentation files (the
+"Software"), to deal in the Software without restriction, including
+without limitation the rights to use, copy, modify, merge, publish,
+distribute, sublicense, and/or sell copies of the Software, and to
+permit persons to whom the Software is furnished to do so, subject to
+the following conditions:
+
+The above copyright notice and this permission notice shall be included
+in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
+EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
+IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
+CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/freebsd/contrib/libpcap/LICENSE b/freebsd/contrib/libpcap/LICENSE
new file mode 100644
index 00000000..a10474d5
--- /dev/null
+++ b/freebsd/contrib/libpcap/LICENSE
@@ -0,0 +1,19 @@
+License: BSD
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/freebsd/contrib/libxo/LICENSE b/freebsd/contrib/libxo/LICENSE
new file mode 100644
index 00000000..874da7b2
--- /dev/null
+++ b/freebsd/contrib/libxo/LICENSE
@@ -0,0 +1,23 @@
+Copyright (c) 2014, Juniper Networks
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+* Redistributions of source code must retain the above copyright notice, this
+ list of conditions and the following disclaimer.
+
+* 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 COPYRIGHT HOLDERS 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 COPYRIGHT HOLDER 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.
diff --git a/freebsd/contrib/tcpdump/LICENSE b/freebsd/contrib/tcpdump/LICENSE
new file mode 100644
index 00000000..dea5f7d5
--- /dev/null
+++ b/freebsd/contrib/tcpdump/LICENSE
@@ -0,0 +1,19 @@
+License: BSD
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions
+are met:
+
+ 1. Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ 3. The names of the authors may not be used to endorse or promote
+ products derived from this software without specific prior
+ written permission.
+
+THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR
+IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
+WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
diff --git a/freebsd/contrib/tcpdump/tcpdump.c b/freebsd/contrib/tcpdump/tcpdump.c
index b1e7f0d1..5b658412 100644
--- a/freebsd/contrib/tcpdump/tcpdump.c
+++ b/freebsd/contrib/tcpdump/tcpdump.c
@@ -139,6 +139,7 @@ The Regents of the University of California. All rights reserved.\n";
#include <sys/sysctl.h>
#include <machine/rtems-bsd-commands.h>
#include <assert.h>
+#include <sched.h>
#include <rtems.h>
#include <rtems/linkersets.h>
#define setpriority(a, b, c)
@@ -206,8 +207,10 @@ cap_channel_t *capdns;
static void error(FORMAT_STRING(const char *), ...) NORETURN PRINTFLIKE(1, 2);
static void warning(FORMAT_STRING(const char *), ...) PRINTFLIKE(1, 2);
static void exit_tcpdump(int) NORETURN;
+#ifndef __rtems__
static RETSIGTYPE cleanup(int);
static RETSIGTYPE child_cleanup(int);
+#endif /* __rtems__ */
static void print_version(void);
static void print_usage(void);
static void show_tstamp_types_and_exit(pcap_t *, const char *device) NORETURN;
@@ -219,6 +222,7 @@ static void show_devices_and_exit (void) NORETURN;
static void print_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
static void dump_packet_and_trunc(u_char *, const struct pcap_pkthdr *, const u_char *);
static void dump_packet(u_char *, const struct pcap_pkthdr *, const u_char *);
+#ifndef __rtems__
static void droproot(const char *, const char *);
#ifdef SIGNAL_REQ_INFO
@@ -232,6 +236,7 @@ RETSIGTYPE requestinfo(int);
#elif defined(HAVE_ALARM)
static void verbose_stats_dump(int sig);
#endif
+#endif /* __rtems__ */
static void info(int);
static u_int packets_captured;
@@ -623,6 +628,7 @@ static const struct option longopts[] = {
{ NULL, 0, NULL, 0 }
};
+#ifndef __rtems__
#ifndef _WIN32
/* Drop root privileges and chroot if necessary */
static void
@@ -654,7 +660,6 @@ droproot(const char *username, const char *chroot_dir)
fprintf(stderr, "dropped privs to %s\n", username);
}
#else
-#ifndef __rtems__
if (initgroups(pw->pw_name, pw->pw_gid) != 0 ||
setgid(pw->pw_gid) != 0 || setuid(pw->pw_uid) != 0) {
fprintf(stderr, "%s: Couldn't change to '%.32s' uid=%lu gid=%lu: %s\n",
@@ -667,7 +672,6 @@ droproot(const char *username, const char *chroot_dir)
else {
fprintf(stderr, "dropped privs to %s\n", username);
}
-#endif /* __rtems__ */
#endif /* HAVE_LIBCAP_NG */
}
else {
@@ -689,6 +693,7 @@ droproot(const char *username, const char *chroot_dir)
}
#endif /* _WIN32 */
+#endif /* __rtems__ */
static int
getWflagChars(int x)
@@ -1196,26 +1201,22 @@ typedef struct {
FILE *in;
pcap_t *pd;
rtems_id master;
+ bool terminate;
} pcap_loop_context;
static void
pcap_loop_monitor(rtems_task_argument arg)
{
- pcap_loop_context *ctx;
+ const pcap_loop_context *ctx;
FILE *in;
pcap_t *pd;
- rtems_id master;
rtems_status_code sc;
- ctx = (pcap_loop_context *)arg;
+ ctx = (const pcap_loop_context *)arg;
in = ctx->in;
pd = ctx->pd;
- master = ctx->master;
-
- sc = rtems_event_transient_send(master);
- assert(sc == RTEMS_SUCCESSFUL);
- while (true) {
+ while (!ctx->terminate) {
int c;
c = fgetc(in);
@@ -1224,19 +1225,22 @@ pcap_loop_monitor(rtems_task_argument arg)
pcap_breakloop(pd);
break;
}
+
+ sched_yield();
}
- rtems_task_delete(RTEMS_SELF);
- assert(0);
+ sc = rtems_event_transient_send(ctx->master);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_task_exit();
}
-static int
-pcap_loop_wrapper(pcap_t *pd, int cnt, pcap_handler cb, u_char *ud)
+static void
+pcap_create_loop_monitor(pcap_loop_context *ctx, pcap_t *pd)
{
rtems_status_code sc;
rtems_task_priority priority;
rtems_id id;
- pcap_loop_context ctx;
sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY,
&priority);
@@ -1246,27 +1250,38 @@ pcap_loop_wrapper(pcap_t *pd, int cnt, pcap_handler cb, u_char *ud)
RTEMS_MINIMUM_STACK_SIZE, RTEMS_DEFAULT_MODES,
RTEMS_DEFAULT_ATTRIBUTES, &id);
if (sc != RTEMS_SUCCESSFUL) {
- fprintf(stderr, "tcpdump: cannot create helper thread: %s\n",
+ error("cannot create pcap loop monitor thread: %s\n",
rtems_status_text(sc));
- return (-1);
}
fprintf(stdout, "tcpdump: press <ENTER> or 'q' or 'Q' to quit\n");
- ctx.in = stdin;
- ctx.pd = pd;
- ctx.master = rtems_task_self();
+ ctx->in = stdin;
+ ctx->pd = pd;
+ ctx->master = rtems_task_self();
+ ctx->terminate = false;
sc = rtems_task_start(id, pcap_loop_monitor,
- (rtems_task_argument)&ctx);
+ (rtems_task_argument)ctx);
assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+pcap_terminate_loop_monitor(pcap_loop_context *ctx)
+{
+ rtems_status_code sc;
+
+ ctx->terminate = true;
sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
assert(sc == RTEMS_SUCCESSFUL);
-
- return (pcap_loop(pd, cnt, cb, ud));
}
-#define pcap_loop(pd, cnt, cb, ud) pcap_loop_wrapper(pd, cnt, cb, ud)
+static void
+destroy_pcap_dumper(void *arg)
+{
+
+ pcap_dump_close(arg);
+}
#endif /* __rtems__ */
int
#ifndef __rtems__
@@ -1283,15 +1298,19 @@ main(int argc, char **argv)
int dlt;
const char *dlt_name;
struct bpf_program fcode;
+#ifndef __rtems__
#ifndef _WIN32
RETSIGTYPE (*oldhandler)(int);
#endif
+#endif /* __rtems__ */
struct dump_info dumpinfo;
u_char *pcap_userdata;
char ebuf[PCAP_ERRBUF_SIZE];
char VFileLine[PATH_MAX + 1];
+#ifndef __rtems__
char *username = NULL;
char *chroot_dir = NULL;
+#endif /* __rtems__ */
char *ret = NULL;
char *end;
#ifdef HAVE_PCAP_FINDALLDEVS
@@ -1663,9 +1682,11 @@ main(int argc, char **argv)
zflag = optarg;
break;
+#ifndef __rtems__
case 'Z':
username = optarg;
break;
+#endif /* __rtems__ */
case '#':
ndo->ndo_packet_number = 1;
@@ -1962,6 +1983,7 @@ main(int argc, char **argv)
init_print(ndo, localnet, netmask, timezone_offset);
+#ifndef __rtems__
#ifndef _WIN32
(void)setsignal(SIGPIPE, cleanup);
(void)setsignal(SIGTERM, cleanup);
@@ -2029,6 +2051,7 @@ main(int argc, char **argv)
}
#endif /* _WIN32 */
+#endif /* __rtems__ */
if (pcap_setfilter(pd, &fcode) < 0)
error("%s", pcap_geterr(pd));
@@ -2123,6 +2146,12 @@ main(int argc, char **argv)
if (Uflag)
pcap_dump_flush(p);
#endif
+#ifdef __rtems__
+ if (rtems_bsd_program_add_destructor(destroy_pcap_dumper, p) ==
+ NULL) {
+ error("cannot add destructor");
+ }
+#endif /* __rtems__ */
} else {
dlt = pcap_datalink(pd);
ndo->ndo_if_printer = get_if_printer(ndo, dlt);
@@ -2130,6 +2159,7 @@ main(int argc, char **argv)
pcap_userdata = (u_char *)ndo;
}
+#ifndef __rtems__
#ifdef SIGNAL_REQ_INFO
/*
* We can't get statistics when reading from a file rather
@@ -2154,6 +2184,7 @@ main(int argc, char **argv)
alarm(1);
#endif
}
+#endif /* __rtems__ */
if (RFileName == NULL) {
/*
@@ -2196,7 +2227,19 @@ main(int argc, char **argv)
#endif /* HAVE_CAPSICUM */
do {
+#ifdef __rtems__
+ pcap_loop_context ctx;
+
+ if (RFileName == NULL) {
+ pcap_create_loop_monitor(&ctx, pd);
+ }
+#endif /* __rtems__ */
status = pcap_loop(pd, cnt, callback, pcap_userdata);
+#ifdef __rtems__
+ if (RFileName == NULL) {
+ pcap_terminate_loop_monitor(&ctx);
+ }
+#endif /* __rtems__ */
if (WFileName == NULL) {
/*
* We're printing packets. Flush the printed output,
@@ -2315,6 +2358,7 @@ main(int argc, char **argv)
exit_tcpdump(status == -1 ? 1 : 0);
}
+#ifndef __rtems__
/* make a clean exit on interrupts */
static RETSIGTYPE
cleanup(int signo _U_)
@@ -2367,6 +2411,7 @@ child_cleanup(int signo _U_)
wait(NULL);
}
#endif /* HAVE_FORK && HAVE_VFORK */
+#endif /* __rtems__ */
static void
info(register int verbose)
@@ -2727,6 +2772,7 @@ print_packet(u_char *user, const struct pcap_pkthdr *h, const u_char *sp)
char Wpcap_version[]="3.1";
#endif
+#ifndef __rtems__
#ifdef SIGNAL_REQ_INFO
RETSIGTYPE requestinfo(int signo _U_)
{
@@ -2755,6 +2801,7 @@ static void verbose_stats_dump(int sig _U_)
alarm(1);
}
#endif
+#endif /* __rtems__ */
USES_APPLE_DEPRECATED_API
static void
diff --git a/freebsd/contrib/wpa/COPYING b/freebsd/contrib/wpa/COPYING
new file mode 100644
index 00000000..5d0115c9
--- /dev/null
+++ b/freebsd/contrib/wpa/COPYING
@@ -0,0 +1,22 @@
+wpa_supplicant and hostapd
+--------------------------
+
+Copyright (c) 2002-2019, Jouni Malinen <j@w1.fi> and contributors
+All Rights Reserved.
+
+
+See the README file for the current license terms.
+
+This software was previously distributed under BSD/GPL v2 dual license
+terms that allowed either of those license alternatives to be
+selected. As of February 11, 2012, the project has chosen to use only
+the BSD license option for future distribution. As such, the GPL v2
+license option is no longer used. It should be noted that the BSD
+license option (the one with advertisement clause removed) is compatible
+with GPL and as such, does not prevent use of this software in projects
+that use GPL.
+
+Some of the files may still include pointers to GPL version 2 license
+terms. However, such copyright and license notifications are maintained
+only for attribution purposes and any distribution of this software
+after February 11, 2012 is no longer under the GPL v2 option.
diff --git a/freebsd/crypto/openssl/LICENSE b/freebsd/crypto/openssl/LICENSE
new file mode 100644
index 00000000..9601ab43
--- /dev/null
+++ b/freebsd/crypto/openssl/LICENSE
@@ -0,0 +1,125 @@
+
+ LICENSE ISSUES
+ ==============
+
+ The OpenSSL toolkit stays under a double license, i.e. both the conditions of
+ the OpenSSL License and the original SSLeay license apply to the toolkit.
+ See below for the actual license texts.
+
+ OpenSSL License
+ ---------------
+
+/* ====================================================================
+ * Copyright (c) 1998-2019 The OpenSSL Project. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in
+ * the documentation and/or other materials provided with the
+ * distribution.
+ *
+ * 3. All advertising materials mentioning features or use of this
+ * software must display the following acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit. (http://www.openssl.org/)"
+ *
+ * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
+ * endorse or promote products derived from this software without
+ * prior written permission. For written permission, please contact
+ * openssl-core@openssl.org.
+ *
+ * 5. Products derived from this software may not be called "OpenSSL"
+ * nor may "OpenSSL" appear in their names without prior written
+ * permission of the OpenSSL Project.
+ *
+ * 6. Redistributions of any form whatsoever must retain the following
+ * acknowledgment:
+ * "This product includes software developed by the OpenSSL Project
+ * for use in the OpenSSL Toolkit (http://www.openssl.org/)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
+ * EXPRESSED 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 OpenSSL PROJECT OR
+ * ITS 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 product includes cryptographic software written by Eric Young
+ * (eay@cryptsoft.com). This product includes software written by Tim
+ * Hudson (tjh@cryptsoft.com).
+ *
+ */
+
+ Original SSLeay License
+ -----------------------
+
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
+ * All rights reserved.
+ *
+ * This package is an SSL implementation written
+ * by Eric Young (eay@cryptsoft.com).
+ * The implementation was written so as to conform with Netscapes SSL.
+ *
+ * This library is free for commercial and non-commercial use as long as
+ * the following conditions are aheared to. The following conditions
+ * apply to all code found in this distribution, be it the RC4, RSA,
+ * lhash, DES, etc., code; not just the SSL code. The SSL documentation
+ * included with this distribution is covered by the same copyright terms
+ * except that the holder is Tim Hudson (tjh@cryptsoft.com).
+ *
+ * Copyright remains Eric Young's, and as such any Copyright notices in
+ * the code are not to be removed.
+ * If this package is used in a product, Eric Young should be given attribution
+ * as the author of the parts of the library used.
+ * This can be in the form of a textual message at program startup or
+ * in documentation (online or textual) provided with the package.
+ *
+ * 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 copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. All advertising materials mentioning features or use of this software
+ * must display the following acknowledgement:
+ * "This product includes cryptographic software written by
+ * Eric Young (eay@cryptsoft.com)"
+ * The word 'cryptographic' can be left out if the rouines from the library
+ * being used are not cryptographic related :-).
+ * 4. If you include any Windows specific code (or a derivative thereof) from
+ * the apps directory (application code) you must include an acknowledgement:
+ * "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
+ *
+ * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``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.
+ *
+ * The licence and distribution terms for any publically available version or
+ * derivative of this code cannot be changed. i.e. this code cannot simply be
+ * copied and put under another distribution licence
+ * [including the GNU Public Licence.]
+ */
+
diff --git a/freebsd/sbin/pfctl/pfctl_parser.c b/freebsd/sbin/pfctl/pfctl_parser.c
index 56f548ba..8a93b39e 100644
--- a/freebsd/sbin/pfctl/pfctl_parser.c
+++ b/freebsd/sbin/pfctl/pfctl_parser.c
@@ -1351,10 +1351,17 @@ get_socket_domain(void)
return (sdom);
}
+#ifdef __rtems__
+static int pfctl_s = -1;
+#endif /* __rtems__ */
int
get_query_socket(void)
{
+#ifndef __rtems__
static int s = -1;
+#else /* __rtems__ */
+#define s pfctl_s
+#endif /* __rtems__ */
if (s == -1) {
if ((s = socket(get_socket_domain(), SOCK_DGRAM, 0)) == -1)
@@ -1362,6 +1369,9 @@ get_query_socket(void)
}
return (s);
+#ifdef __rtems__
+#undef s
+#endif /* __rtems__ */
}
/*
diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
index 3d805ea1..c43866bb 100644
--- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
+++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-namespace.h
@@ -35,6 +35,7 @@
#define parseport _bsd_pfctl_parseport
#define pfctl_cmdline_symset _bsd_pfctl_pfctl_cmdline_symset
#define pfctl_load_anchors _bsd_pfctl_pfctl_load_anchors
+#define pfctl_s _bsd_pfctl_s
#define pfctlychar _bsd_pfctl_pfctlychar
#define pfctlydebug _bsd_pfctl_pfctlydebug
#define pfctlyerrflag _bsd_pfctl_pfctlyerrflag
diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h
index 4c39bea9..59b3541d 100644
--- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h
+++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_altq-data.h
@@ -4,8 +4,6 @@
/* pfctl_altq.c */
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static char r2sbuf[][16]);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int idx);
-RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc lssc);
-RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct gen_sc rtsc);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct hsearch_data if_map);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct hsearch_data qid_map);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct hsearch_data queue_map);
diff --git a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_parser-data.h b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_parser-data.h
index f9a7f49f..ac6655cc 100644
--- a/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_parser-data.h
+++ b/freebsd/sbin/pfctl/rtems-bsd-pfctl-pfctl_parser-data.h
@@ -4,3 +4,4 @@
/* pfctl_parser.c */
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct hsearch_data isgroup_map);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static struct node_host *iftab);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_pfctl, static int pfctl_s);
diff --git a/freebsd/sbin/ping6/ping6.c b/freebsd/sbin/ping6/ping6.c
index db3ab05a..96bd60e3 100644
--- a/freebsd/sbin/ping6/ping6.c
+++ b/freebsd/sbin/ping6/ping6.c
@@ -115,6 +115,7 @@ __FBSDID("$FreeBSD$");
#include <getopt.h>
#include <machine/rtems-bsd-program.h>
#include <machine/rtems-bsd-commands.h>
+#include <rtems/libio_.h>
#endif /* __rtems__ */
#include <sys/param.h>
#include <sys/capsicum.h>
@@ -1198,7 +1199,13 @@ main(int argc, char *argv[])
struct timespec now, timeout;
struct msghdr m;
struct iovec iov[2];
+#ifndef __rtems__
fd_set rfds;
+#else /* __rtems__ */
+ fd_set big_enough_rfds[howmany(rtems_libio_number_iops,
+ sizeof(fd_set) * 8)];
+#define rfds (*(fd_set *)(&big_enough_rfds[0]))
+#endif /* __rtems__ */
int n;
/* signal handling */
@@ -1211,7 +1218,11 @@ main(int argc, char *argv[])
continue;
}
#endif
+#ifndef __rtems__
FD_ZERO(&rfds);
+#else /* __rtems__ */
+ memset(big_enough_rfds, 0, sizeof(big_enough_rfds));
+#endif /* __rtems__ */
FD_SET(srecv, &rfds);
clock_gettime(CLOCK_MONOTONIC, &now);
timespecadd(&last, &intvl, &timeout);
diff --git a/freebsd/sys/contrib/libsodium/LICENSE b/freebsd/sys/contrib/libsodium/LICENSE
new file mode 100644
index 00000000..1553d6bb
--- /dev/null
+++ b/freebsd/sys/contrib/libsodium/LICENSE
@@ -0,0 +1,18 @@
+/*
+ * ISC License
+ *
+ * Copyright (c) 2013-2018
+ * Frank Denis <j at pureftpd dot org>
+ *
+ * Permission to use, copy, modify, and/or distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
diff --git a/freebsd/sys/dev/dc/if_dc.c b/freebsd/sys/dev/dc/if_dc.c
index 7fc0ef54..b36967da 100644
--- a/freebsd/sys/dev/dc/if_dc.c
+++ b/freebsd/sys/dev/dc/if_dc.c
@@ -156,6 +156,10 @@ MODULE_DEPEND(dc, miibus, 1, 1, 1);
* Various supported device vendors/types and their names.
*/
static const struct dc_type dc_devs[] = {
+#ifdef __rtems__
+ { DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21140A), 0,
+ "Intel 21140A 10/100BaseTX" },
+#endif /* __rtems__ */
{ DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143), 0,
"Intel 21143 10/100BaseTX" },
{ DC_DEVID(DC_VENDORID_DAVICOM, DC_DEVICEID_DM9009), 0,
@@ -2076,6 +2080,9 @@ dc_attach(device_t dev)
dc_eeprom_width(sc);
switch (sc->dc_info->dc_devid) {
+#ifdef __rtems__
+ case DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21140A):
+#endif /* __rtems__ */
case DC_DEVID(DC_VENDORID_DEC, DC_DEVICEID_21143):
sc->dc_type = DC_TYPE_21143;
sc->dc_flags |= DC_TX_POLL | DC_TX_USE_TX_INTR;
diff --git a/freebsd/sys/dev/dc/if_dcreg.h b/freebsd/sys/dev/dc/if_dcreg.h
index 9ae26cc6..1c5d39a0 100644
--- a/freebsd/sys/dev/dc/if_dcreg.h
+++ b/freebsd/sys/dev/dc/if_dcreg.h
@@ -824,6 +824,13 @@ struct dc_softc {
*/
#define DC_VENDORID_DEC 0x1011
+#ifdef __rtems__
+/*
+ * DEC/Intel 21140 PCI device ID
+ */
+#define DC_DEVICEID_21140A 0x0009
+
+#endif /* __rtems__ */
/*
* DEC/Intel 21143 PCI device ID
*/
diff --git a/freebsd/sys/dev/e1000/LICENSE b/freebsd/sys/dev/e1000/LICENSE
new file mode 100644
index 00000000..f70a7cbd
--- /dev/null
+++ b/freebsd/sys/dev/e1000/LICENSE
@@ -0,0 +1,31 @@
+$FreeBSD$
+
+ Copyright (c) 2001-2010, Intel Corporation
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are met:
+
+ 1. Redistributions of source code must retain the above copyright notice,
+ this list of conditions and the following disclaimer.
+
+ 2. Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in the
+ documentation and/or other materials provided with the distribution.
+
+ 3. Neither the name of the Intel Corporation nor the names of its
+ contributors may be used to endorse or promote products derived from
+ this software without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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.
+
diff --git a/freebsd/sys/dev/usb/controller/ehci_pci.c b/freebsd/sys/dev/usb/controller/ehci_pci.c
new file mode 100644
index 00000000..d1320278
--- /dev/null
+++ b/freebsd/sys/dev/usb/controller/ehci_pci.c
@@ -0,0 +1,592 @@
+#include <machine/rtems-bsd-kernel-space.h>
+
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-NetBSD
+ *
+ * Copyright (c) 1998 The NetBSD Foundation, Inc.
+ * All rights reserved.
+ *
+ * This code is derived from software contributed to The NetBSD Foundation
+ * by Lennart Augustsson (augustss@carlstedt.se) at
+ * Carlstedt Research & Technology.
+ *
+ * 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 NETBSD FOUNDATION, INC. 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 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.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+/*
+ * USB Enhanced Host Controller Driver, a.k.a. USB 2.0 controller.
+ *
+ * The EHCI 1.0 spec can be found at
+ * http://developer.intel.com/technology/usb/download/ehci-r10.pdf
+ * and the USB 2.0 spec at
+ * http://www.usb.org/developers/docs/usb_20.zip
+ */
+
+/* The low level controller code for EHCI has been split into
+ * PCI probes and EHCI specific code. This was done to facilitate the
+ * sharing of code between *BSD's
+ */
+
+#include <sys/stdint.h>
+#include <sys/stddef.h>
+#include <sys/param.h>
+#include <sys/queue.h>
+#include <sys/types.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/bus.h>
+#include <sys/module.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/condvar.h>
+#include <sys/sysctl.h>
+#include <sys/sx.h>
+#include <rtems/bsd/sys/unistd.h>
+#include <sys/callout.h>
+#include <sys/malloc.h>
+#include <sys/priv.h>
+
+#include <dev/usb/usb.h>
+#include <dev/usb/usbdi.h>
+
+#include <dev/usb/usb_core.h>
+#include <dev/usb/usb_busdma.h>
+#include <dev/usb/usb_process.h>
+#include <dev/usb/usb_util.h>
+
+#include <dev/usb/usb_controller.h>
+#include <dev/usb/usb_bus.h>
+#include <dev/usb/usb_pci.h>
+#include <dev/usb/controller/ehci.h>
+#include <dev/usb/controller/ehcireg.h>
+#include <rtems/bsd/local/usb_if.h>
+
+#define PCI_EHCI_VENDORID_ACERLABS 0x10b9
+#define PCI_EHCI_VENDORID_AMD 0x1022
+#define PCI_EHCI_VENDORID_APPLE 0x106b
+#define PCI_EHCI_VENDORID_ATI 0x1002
+#define PCI_EHCI_VENDORID_CMDTECH 0x1095
+#define PCI_EHCI_VENDORID_INTEL 0x8086
+#define PCI_EHCI_VENDORID_NEC 0x1033
+#define PCI_EHCI_VENDORID_OPTI 0x1045
+#define PCI_EHCI_VENDORID_PHILIPS 0x1131
+#define PCI_EHCI_VENDORID_SIS 0x1039
+#define PCI_EHCI_VENDORID_NVIDIA 0x12D2
+#define PCI_EHCI_VENDORID_NVIDIA2 0x10DE
+#define PCI_EHCI_VENDORID_VIA 0x1106
+
+static device_probe_t ehci_pci_probe;
+static device_attach_t ehci_pci_attach;
+static device_detach_t ehci_pci_detach;
+static usb_take_controller_t ehci_pci_take_controller;
+
+static const char *
+ehci_pci_match(device_t self)
+{
+ uint32_t device_id = pci_get_devid(self);
+
+ switch (device_id) {
+ case 0x523910b9:
+ return "ALi M5239 USB 2.0 controller";
+
+ case 0x10227463:
+ return "AMD 8111 USB 2.0 controller";
+
+ case 0x20951022:
+ return ("AMD CS5536 (Geode) USB 2.0 controller");
+ case 0x78081022:
+ return ("AMD FCH USB 2.0 controller");
+
+ case 0x43451002:
+ return "ATI SB200 USB 2.0 controller";
+ case 0x43731002:
+ return "ATI SB400 USB 2.0 controller";
+ case 0x43961002:
+ return ("AMD SB7x0/SB8x0/SB9x0 USB 2.0 controller");
+
+ case 0x0f348086:
+ return ("Intel BayTrail USB 2.0 controller");
+ case 0x1c268086:
+ return ("Intel Cougar Point USB 2.0 controller");
+ case 0x1c2d8086:
+ return ("Intel Cougar Point USB 2.0 controller");
+ case 0x1d268086:
+ return ("Intel Patsburg USB 2.0 controller");
+ case 0x1d2d8086:
+ return ("Intel Patsburg USB 2.0 controller");
+ case 0x1e268086:
+ return ("Intel Panther Point USB 2.0 controller");
+ case 0x1e2d8086:
+ return ("Intel Panther Point USB 2.0 controller");
+ case 0x1f2c8086:
+ return ("Intel Avoton USB 2.0 controller");
+ case 0x25ad8086:
+ return "Intel 6300ESB USB 2.0 controller";
+ case 0x24cd8086:
+ return "Intel 82801DB/L/M (ICH4) USB 2.0 controller";
+ case 0x24dd8086:
+ return "Intel 82801EB/R (ICH5) USB 2.0 controller";
+ case 0x265c8086:
+ return "Intel 82801FB (ICH6) USB 2.0 controller";
+ case 0x268c8086:
+ return ("Intel 63XXESB USB 2.0 controller");
+ case 0x27cc8086:
+ return "Intel 82801GB/R (ICH7) USB 2.0 controller";
+ case 0x28368086:
+ return "Intel 82801H (ICH8) USB 2.0 controller USB2-A";
+ case 0x283a8086:
+ return "Intel 82801H (ICH8) USB 2.0 controller USB2-B";
+ case 0x293a8086:
+ return "Intel 82801I (ICH9) USB 2.0 controller";
+ case 0x293c8086:
+ return "Intel 82801I (ICH9) USB 2.0 controller";
+ case 0x3a3a8086:
+ return "Intel 82801JI (ICH10) USB 2.0 controller USB-A";
+ case 0x3a3c8086:
+ return "Intel 82801JI (ICH10) USB 2.0 controller USB-B";
+ case 0x3b348086:
+ return ("Intel PCH USB 2.0 controller USB-A");
+ case 0x3b3c8086:
+ return ("Intel PCH USB 2.0 controller USB-B");
+ case 0x8c268086:
+ return ("Intel Lynx Point USB 2.0 controller USB-A");
+ case 0x8c2d8086:
+ return ("Intel Lynx Point USB 2.0 controller USB-B");
+ case 0x8ca68086:
+ return ("Intel Wildcat Point USB 2.0 controller USB-A");
+ case 0x8cad8086:
+ return ("Intel Wildcat Point USB 2.0 controller USB-B");
+ case 0x8d268086:
+ return ("Intel Wellsburg USB 2.0 controller");
+ case 0x8d2d8086:
+ return ("Intel Wellsburg USB 2.0 controller");
+ case 0x9c268086:
+ return ("Intel Lynx Point-LP USB 2.0 controller");
+ case 0x9ca68086:
+ return ("Intel Wildcat Point-LP USB 2.0 controller");
+
+ case 0x00e01033:
+ return ("NEC uPD 72010x USB 2.0 controller");
+
+ case 0x006810de:
+ return "NVIDIA nForce2 USB 2.0 controller";
+ case 0x008810de:
+ return "NVIDIA nForce2 Ultra 400 USB 2.0 controller";
+ case 0x00d810de:
+ return "NVIDIA nForce3 USB 2.0 controller";
+ case 0x00e810de:
+ return "NVIDIA nForce3 250 USB 2.0 controller";
+ case 0x005b10de:
+ return "NVIDIA nForce CK804 USB 2.0 controller";
+ case 0x036d10de:
+ return "NVIDIA nForce MCP55 USB 2.0 controller";
+ case 0x03f210de:
+ return "NVIDIA nForce MCP61 USB 2.0 controller";
+ case 0x0aa610de:
+ return "NVIDIA nForce MCP79 USB 2.0 controller";
+ case 0x0aa910de:
+ return "NVIDIA nForce MCP79 USB 2.0 controller";
+ case 0x0aaa10de:
+ return "NVIDIA nForce MCP79 USB 2.0 controller";
+
+ case 0x15621131:
+ return "Philips ISP156x USB 2.0 controller";
+
+ case 0x31041106:
+ return ("VIA VT6202 USB 2.0 controller");
+
+ default:
+ break;
+ }
+
+ if ((pci_get_class(self) == PCIC_SERIALBUS)
+ && (pci_get_subclass(self) == PCIS_SERIALBUS_USB)
+ && (pci_get_progif(self) == PCI_INTERFACE_EHCI)) {
+ return ("EHCI (generic) USB 2.0 controller");
+ }
+ return (NULL); /* dunno */
+}
+
+static int
+ehci_pci_probe(device_t self)
+{
+ const char *desc = ehci_pci_match(self);
+
+ if (desc) {
+ device_set_desc(self, desc);
+ return (BUS_PROBE_DEFAULT);
+ } else {
+ return (ENXIO);
+ }
+}
+
+static void
+ehci_pci_ati_quirk(device_t self, uint8_t is_sb700)
+{
+ device_t smbdev;
+ uint32_t val;
+
+ if (is_sb700) {
+ /* Lookup SMBUS PCI device */
+ smbdev = pci_find_device(PCI_EHCI_VENDORID_ATI, 0x4385);
+ if (smbdev == NULL)
+ return;
+ val = pci_get_revid(smbdev);
+ if (val != 0x3a && val != 0x3b)
+ return;
+ }
+
+ /*
+ * Note: this bit is described as reserved in SB700
+ * Register Reference Guide.
+ */
+ val = pci_read_config(self, 0x53, 1);
+ if (!(val & 0x8)) {
+ val |= 0x8;
+ pci_write_config(self, 0x53, val, 1);
+ device_printf(self, "AMD SB600/700 quirk applied\n");
+ }
+}
+
+static void
+ehci_pci_via_quirk(device_t self)
+{
+ uint32_t val;
+
+ if ((pci_get_device(self) == 0x3104) &&
+ ((pci_get_revid(self) & 0xf0) == 0x60)) {
+ /* Correct schedule sleep time to 10us */
+ val = pci_read_config(self, 0x4b, 1);
+ if (val & 0x20)
+ return;
+ val |= 0x20;
+ pci_write_config(self, 0x4b, val, 1);
+ device_printf(self, "VIA-quirk applied\n");
+ }
+}
+
+static int
+ehci_pci_attach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ int err;
+ int rid;
+
+ /* initialise some bus fields */
+ sc->sc_bus.parent = self;
+ sc->sc_bus.devices = sc->sc_devices;
+ sc->sc_bus.devices_max = EHCI_MAX_DEVICES;
+ sc->sc_bus.dma_bits = 32;
+
+ /* get all DMA memory */
+ if (usb_bus_mem_alloc_all(&sc->sc_bus,
+ USB_GET_DMA_TAG(self), &ehci_iterate_hw_softc)) {
+ return (ENOMEM);
+ }
+
+ pci_enable_busmaster(self);
+
+ switch (pci_read_config(self, PCI_USBREV, 1) & PCI_USB_REV_MASK) {
+ case PCI_USB_REV_PRE_1_0:
+ case PCI_USB_REV_1_0:
+ case PCI_USB_REV_1_1:
+ /*
+ * NOTE: some EHCI USB controllers have the wrong USB
+ * revision number. It appears those controllers are
+ * fully compliant so we just ignore this value in
+ * some common cases.
+ */
+ device_printf(self, "pre-2.0 USB revision (ignored)\n");
+ /* fallthrough */
+ case PCI_USB_REV_2_0:
+ break;
+ default:
+ /* Quirk for Parallels Desktop 4.0 */
+ device_printf(self, "USB revision is unknown. Assuming v2.0.\n");
+ break;
+ }
+
+ rid = PCI_CBMEM;
+ sc->sc_io_res = bus_alloc_resource_any(self, SYS_RES_MEMORY, &rid,
+ RF_ACTIVE);
+ if (!sc->sc_io_res) {
+ device_printf(self, "Could not map memory\n");
+ goto error;
+ }
+ sc->sc_io_tag = rman_get_bustag(sc->sc_io_res);
+ sc->sc_io_hdl = rman_get_bushandle(sc->sc_io_res);
+ sc->sc_io_size = rman_get_size(sc->sc_io_res);
+
+ rid = 0;
+ sc->sc_irq_res = bus_alloc_resource_any(self, SYS_RES_IRQ, &rid,
+ RF_SHAREABLE | RF_ACTIVE);
+ if (sc->sc_irq_res == NULL) {
+ device_printf(self, "Could not allocate irq\n");
+ goto error;
+ }
+ sc->sc_bus.bdev = device_add_child(self, "usbus", -1);
+ if (!sc->sc_bus.bdev) {
+ device_printf(self, "Could not add USB device\n");
+ goto error;
+ }
+ device_set_ivars(sc->sc_bus.bdev, &sc->sc_bus);
+
+ /*
+ * ehci_pci_match will never return NULL if ehci_pci_probe
+ * succeeded
+ */
+ device_set_desc(sc->sc_bus.bdev, ehci_pci_match(self));
+ switch (pci_get_vendor(self)) {
+ case PCI_EHCI_VENDORID_ACERLABS:
+ sprintf(sc->sc_vendor, "AcerLabs");
+ break;
+ case PCI_EHCI_VENDORID_AMD:
+ sprintf(sc->sc_vendor, "AMD");
+ break;
+ case PCI_EHCI_VENDORID_APPLE:
+ sprintf(sc->sc_vendor, "Apple");
+ break;
+ case PCI_EHCI_VENDORID_ATI:
+ sprintf(sc->sc_vendor, "ATI");
+ break;
+ case PCI_EHCI_VENDORID_CMDTECH:
+ sprintf(sc->sc_vendor, "CMDTECH");
+ break;
+ case PCI_EHCI_VENDORID_INTEL:
+ sprintf(sc->sc_vendor, "Intel");
+ break;
+ case PCI_EHCI_VENDORID_NEC:
+ sprintf(sc->sc_vendor, "NEC");
+ break;
+ case PCI_EHCI_VENDORID_OPTI:
+ sprintf(sc->sc_vendor, "OPTi");
+ break;
+ case PCI_EHCI_VENDORID_PHILIPS:
+ sprintf(sc->sc_vendor, "Philips");
+ break;
+ case PCI_EHCI_VENDORID_SIS:
+ sprintf(sc->sc_vendor, "SiS");
+ break;
+ case PCI_EHCI_VENDORID_NVIDIA:
+ case PCI_EHCI_VENDORID_NVIDIA2:
+ sprintf(sc->sc_vendor, "nVidia");
+ break;
+ case PCI_EHCI_VENDORID_VIA:
+ sprintf(sc->sc_vendor, "VIA");
+ break;
+ default:
+ if (bootverbose)
+ device_printf(self, "(New EHCI DeviceId=0x%08x)\n",
+ pci_get_devid(self));
+ sprintf(sc->sc_vendor, "(0x%04x)", pci_get_vendor(self));
+ }
+
+#if (__FreeBSD_version >= 700031)
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ NULL, (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+#else
+ err = bus_setup_intr(self, sc->sc_irq_res, INTR_TYPE_BIO | INTR_MPSAFE,
+ (driver_intr_t *)ehci_interrupt, sc, &sc->sc_intr_hdl);
+#endif
+ if (err) {
+ device_printf(self, "Could not setup irq, %d\n", err);
+ sc->sc_intr_hdl = NULL;
+ goto error;
+ }
+ ehci_pci_take_controller(self);
+
+ /* Undocumented quirks taken from Linux */
+
+ switch (pci_get_vendor(self)) {
+ case PCI_EHCI_VENDORID_ATI:
+ /* SB600 and SB700 EHCI quirk */
+ switch (pci_get_device(self)) {
+ case 0x4386:
+ ehci_pci_ati_quirk(self, 0);
+ break;
+ case 0x4396:
+ ehci_pci_ati_quirk(self, 1);
+ break;
+ default:
+ break;
+ }
+ break;
+
+ case PCI_EHCI_VENDORID_VIA:
+ ehci_pci_via_quirk(self);
+ break;
+
+ default:
+ break;
+ }
+
+ /* Dropped interrupts workaround */
+ switch (pci_get_vendor(self)) {
+ case PCI_EHCI_VENDORID_ATI:
+ case PCI_EHCI_VENDORID_VIA:
+ sc->sc_flags |= EHCI_SCFLG_LOSTINTRBUG;
+ if (bootverbose)
+ device_printf(self,
+ "Dropped interrupts workaround enabled\n");
+ break;
+ default:
+ break;
+ }
+
+ /* Doorbell feature workaround */
+ switch (pci_get_vendor(self)) {
+ case PCI_EHCI_VENDORID_NVIDIA:
+ case PCI_EHCI_VENDORID_NVIDIA2:
+ sc->sc_flags |= EHCI_SCFLG_IAADBUG;
+ if (bootverbose)
+ device_printf(self,
+ "Doorbell workaround enabled\n");
+ break;
+ default:
+ break;
+ }
+
+ err = ehci_init(sc);
+ if (!err) {
+ err = device_probe_and_attach(sc->sc_bus.bdev);
+ }
+ if (err) {
+ device_printf(self, "USB init failed err=%d\n", err);
+ goto error;
+ }
+ return (0);
+
+error:
+ ehci_pci_detach(self);
+ return (ENXIO);
+}
+
+static int
+ehci_pci_detach(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+
+ /* during module unload there are lots of children leftover */
+ device_delete_children(self);
+
+ pci_disable_busmaster(self);
+
+ if (sc->sc_irq_res && sc->sc_intr_hdl) {
+ /*
+ * only call ehci_detach() after ehci_init()
+ */
+ ehci_detach(sc);
+
+ int err = bus_teardown_intr(self, sc->sc_irq_res, sc->sc_intr_hdl);
+
+ if (err)
+ /* XXX or should we panic? */
+ device_printf(self, "Could not tear down irq, %d\n",
+ err);
+ sc->sc_intr_hdl = NULL;
+ }
+ if (sc->sc_irq_res) {
+ bus_release_resource(self, SYS_RES_IRQ, 0, sc->sc_irq_res);
+ sc->sc_irq_res = NULL;
+ }
+ if (sc->sc_io_res) {
+ bus_release_resource(self, SYS_RES_MEMORY, PCI_CBMEM,
+ sc->sc_io_res);
+ sc->sc_io_res = NULL;
+ }
+ usb_bus_mem_free_all(&sc->sc_bus, &ehci_iterate_hw_softc);
+
+ return (0);
+}
+
+static int
+ehci_pci_take_controller(device_t self)
+{
+ ehci_softc_t *sc = device_get_softc(self);
+ uint32_t cparams;
+ uint32_t eec;
+ uint16_t to;
+ uint8_t eecp;
+ uint8_t bios_sem;
+
+ cparams = EREAD4(sc, EHCI_HCCPARAMS);
+
+ /* Synchronise with the BIOS if it owns the controller. */
+ for (eecp = EHCI_HCC_EECP(cparams); eecp != 0;
+ eecp = EHCI_EECP_NEXT(eec)) {
+ eec = pci_read_config(self, eecp, 4);
+ if (EHCI_EECP_ID(eec) != EHCI_EC_LEGSUP) {
+ continue;
+ }
+ bios_sem = pci_read_config(self, eecp +
+ EHCI_LEGSUP_BIOS_SEM, 1);
+ if (bios_sem == 0) {
+ continue;
+ }
+ device_printf(sc->sc_bus.bdev, "waiting for BIOS "
+ "to give up control\n");
+ pci_write_config(self, eecp +
+ EHCI_LEGSUP_OS_SEM, 1, 1);
+ to = 500;
+ while (1) {
+ bios_sem = pci_read_config(self, eecp +
+ EHCI_LEGSUP_BIOS_SEM, 1);
+ if (bios_sem == 0)
+ break;
+
+ if (--to == 0) {
+ device_printf(sc->sc_bus.bdev,
+ "timed out waiting for BIOS\n");
+ break;
+ }
+ usb_pause_mtx(NULL, hz / 100); /* wait 10ms */
+ }
+ }
+ return (0);
+}
+
+static device_method_t ehci_pci_methods[] = {
+ /* Device interface */
+ DEVMETHOD(device_probe, ehci_pci_probe),
+ DEVMETHOD(device_attach, ehci_pci_attach),
+ DEVMETHOD(device_detach, ehci_pci_detach),
+ DEVMETHOD(device_suspend, bus_generic_suspend),
+ DEVMETHOD(device_resume, bus_generic_resume),
+ DEVMETHOD(device_shutdown, bus_generic_shutdown),
+ DEVMETHOD(usb_take_controller, ehci_pci_take_controller),
+
+ DEVMETHOD_END
+};
+
+static driver_t ehci_driver = {
+ .name = "ehci",
+ .methods = ehci_pci_methods,
+ .size = sizeof(struct ehci_softc),
+};
+
+static devclass_t ehci_devclass;
+
+DRIVER_MODULE(ehci, pci, ehci_driver, ehci_devclass, 0, 0);
+MODULE_DEPEND(ehci, usb, 1, 1, 1);
diff --git a/freebsd/sys/dev/usb/usb_pci.h b/freebsd/sys/dev/usb/usb_pci.h
new file mode 100644
index 00000000..86e8cb39
--- /dev/null
+++ b/freebsd/sys/dev/usb/usb_pci.h
@@ -0,0 +1,43 @@
+/* $FreeBSD$ */
+/*-
+ * SPDX-License-Identifier: BSD-2-Clause-FreeBSD
+ *
+ * Copyright (c) 2008 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_PCI_H_
+#define _USB_PCI_H_
+
+/*
+ * We don't want the following files included everywhere, that's why
+ * they are in a separate file.
+ */
+#ifndef USB_GLOBAL_INCLUDE_FILE
+#include <dev/pci/pcireg.h>
+#include <dev/pci/pcivar.h>
+
+#include <sys/rman.h>
+#endif
+
+#endif /* _USB_PCI_H_ */
diff --git a/freebsd/sys/i386/include/machine/intr_machdep.h b/freebsd/sys/i386/include/machine/intr_machdep.h
deleted file mode 100644
index a0b28387..00000000
--- a/freebsd/sys/i386/include/machine/intr_machdep.h
+++ /dev/null
@@ -1,6 +0,0 @@
-/*-
- * This file is in the public domain.
- */
-/* $FreeBSD$ */
-
-#include <x86/intr_machdep.h>
diff --git a/freebsd/usr.sbin/ifmcstat/ifmcstat.c b/freebsd/usr.sbin/ifmcstat/ifmcstat.c
new file mode 100644
index 00000000..19acaf62
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/ifmcstat.c
@@ -0,0 +1,1295 @@
+#include <machine/rtems-bsd-user-space.h>
+
+#ifdef __rtems__
+#include "rtems-bsd-ifmcstat-namespace.h"
+#include "rtems-bsd-ifmcstat-ifmcstat-data.h"
+#endif /* __rtems__ */
+
+/* $KAME: ifmcstat.c,v 1.48 2006/11/15 05:13:59 itojun Exp $ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 2007-2009 Bruce Simpson.
+ * Copyright (C) 1995, 1996, 1997, and 1998 WIDE Project.
+ * All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the project nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE PROJECT 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 PROJECT 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.
+ */
+
+#ifdef __rtems__
+#define __need_getopt_newlib
+#include <getopt.h>
+#include <machine/rtems-bsd-program.h>
+#include <machine/rtems-bsd-commands.h>
+#include <rtems/libio_.h>
+#endif /* __rtems__ */
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <sys/sysctl.h>
+#include <sys/socket.h>
+#include <sys/queue.h>
+#include <sys/tree.h>
+
+#include <net/if.h>
+#include <net/if_types.h>
+#include <net/if_dl.h>
+#include <net/route.h>
+
+#include <netinet/in.h>
+#include <netinet/in_var.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/igmp.h>
+#include <netinet/if_ether.h>
+#include <netinet/igmp_var.h>
+
+#ifdef INET6
+#include <netinet/icmp6.h>
+#include <netinet6/mld6_var.h>
+#endif /* INET6 */
+
+#include <arpa/inet.h>
+#include <netdb.h>
+
+#include <stddef.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <ctype.h>
+#include <err.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <limits.h>
+#include <ifaddrs.h>
+#include <sysexits.h>
+#include <unistd.h>
+
+#ifdef KVM
+/*
+ * Currently the KVM build is broken. To be fixed it requires uncovering
+ * large amount of _KERNEL code in include files, and it is also very
+ * tentative to internal kernel ABI changes. If anyone wishes to restore
+ * it, please move it out of src/usr.sbin to src/tools/tools.
+ */
+#include <kvm.h>
+#include <nlist.h>
+#endif
+
+/* XXX: This file currently assumes INET support in the base system. */
+#ifndef INET
+#define INET
+#endif
+
+extern void printb(const char *, unsigned int, const char *);
+
+union sockunion {
+ struct sockaddr_storage ss;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+#ifdef INET
+ struct sockaddr_in sin;
+#endif
+#ifdef INET6
+ struct sockaddr_in6 sin6;
+#endif
+};
+typedef union sockunion sockunion_t;
+
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
+uint32_t ifindex = 0;
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
+int af = AF_UNSPEC;
+#ifdef WITH_KVM
+int Kflag = 0;
+#endif
+#ifdef __rtems__
+static
+#endif /* __rtems__ */
+int vflag = 0;
+
+#define sa_dl_equal(a1, a2) \
+ ((((struct sockaddr_dl *)(a1))->sdl_len == \
+ ((struct sockaddr_dl *)(a2))->sdl_len) && \
+ (bcmp(LLADDR((struct sockaddr_dl *)(a1)), \
+ LLADDR((struct sockaddr_dl *)(a2)), \
+ ((struct sockaddr_dl *)(a1))->sdl_alen) == 0))
+
+/*
+ * Most of the code in this utility is to support the use of KVM for
+ * post-mortem debugging of the multicast code.
+ */
+#ifdef WITH_KVM
+
+#ifdef INET
+static void if_addrlist(struct ifaddr *);
+static struct in_multi *
+ in_multientry(struct in_multi *);
+#endif /* INET */
+
+#ifdef INET6
+static void if6_addrlist(struct ifaddr *);
+static struct in6_multi *
+ in6_multientry(struct in6_multi *);
+#endif /* INET6 */
+
+static void kread(u_long, void *, int);
+static void ll_addrlist(struct ifaddr *);
+
+static int ifmcstat_kvm(const char *kernel, const char *core);
+
+#define KREAD(addr, buf, type) \
+ kread((u_long)addr, (void *)buf, sizeof(type))
+
+kvm_t *kvmd;
+struct nlist nl[] = {
+ { "_ifnet", 0, 0, 0, 0, },
+ { "", 0, 0, 0, 0, },
+};
+#define N_IFNET 0
+
+#endif /* WITH_KVM */
+
+static int ifmcstat_getifmaddrs(void);
+#ifdef INET
+static void in_ifinfo(struct igmp_ifinfo *);
+static const char * inm_mode(u_int mode);
+#endif
+#ifdef INET6
+static void in6_ifinfo(struct mld_ifinfo *);
+static const char * inet6_n2a(struct in6_addr *, uint32_t);
+#endif
+#ifdef __rtems__
+static int main(int argc, char *argv[]);
+
+RTEMS_LINKER_RWSET(bsd_prog_ifmcstat, char);
+
+int
+rtems_bsd_command_ifmcstat(int argc, char *argv[])
+{
+ int exit_code;
+ void *data_begin;
+ size_t data_size;
+
+ data_begin = RTEMS_LINKER_SET_BEGIN(bsd_prog_ifmcstat);
+ data_size = RTEMS_LINKER_SET_SIZE(bsd_prog_ifmcstat);
+
+ rtems_bsd_program_lock();
+ exit_code = rtems_bsd_program_call_main_with_data_restore("ifmcstat",
+ main, argc, argv, data_begin, data_size);
+ rtems_bsd_program_unlock();
+
+ return exit_code;
+}
+#else /* __rtems__ */
+int main(int, char **);
+#endif /* __rtems__ */
+
+static void
+usage()
+{
+
+ fprintf(stderr,
+ "usage: ifmcstat [-i interface] [-f address family]"
+ " [-v]"
+#ifdef WITH_KVM
+ " [-K] [-M core] [-N system]"
+#endif
+ "\n");
+ exit(EX_USAGE);
+}
+
+static const char * const options = "i:f:vM:N:"
+#ifdef WITH_KVM
+ "K"
+#endif
+ ;
+
+int
+main(int argc, char **argv)
+{
+ int c, error;
+#ifdef WITH_KVM
+ const char *kernel = NULL;
+ const char *core = NULL;
+#endif
+
+ while ((c = getopt(argc, argv, options)) != -1) {
+ switch (c) {
+ case 'i':
+ if ((ifindex = if_nametoindex(optarg)) == 0) {
+ fprintf(stderr, "%s: unknown interface\n",
+ optarg);
+ exit(EX_NOHOST);
+ }
+ break;
+
+ case 'f':
+#ifdef INET
+ if (strcmp(optarg, "inet") == 0) {
+ af = AF_INET;
+ break;
+ }
+#endif
+#ifdef INET6
+ if (strcmp(optarg, "inet6") == 0) {
+ af = AF_INET6;
+ break;
+ }
+#endif
+ if (strcmp(optarg, "link") == 0) {
+ af = AF_LINK;
+ break;
+ }
+ fprintf(stderr, "%s: unknown address family\n", optarg);
+ exit(EX_USAGE);
+ /*NOTREACHED*/
+ break;
+
+#ifdef WITH_KVM
+ case 'K':
+ ++Kflag;
+ break;
+#endif
+
+ case 'v':
+ ++vflag;
+ break;
+
+#ifdef WITH_KVM
+ case 'M':
+ core = strdup(optarg);
+ break;
+
+ case 'N':
+ kernel = strdup(optarg);
+ break;
+#endif
+
+ default:
+ usage();
+ break;
+ /*NOTREACHED*/
+ }
+ }
+
+ if (af == AF_LINK && vflag)
+ usage();
+
+#ifdef WITH_KVM
+ if (Kflag)
+ error = ifmcstat_kvm(kernel, core);
+ /*
+ * If KVM failed, and user did not explicitly specify a core file,
+ * or force KVM backend to be disabled, try the sysctl backend.
+ */
+ if (!Kflag || (error != 0 && (core == NULL && kernel == NULL)))
+#endif
+ error = ifmcstat_getifmaddrs();
+ if (error != 0)
+ exit(EX_OSERR);
+
+ exit(EX_OK);
+ /*NOTREACHED*/
+}
+
+#ifdef INET
+
+static void
+in_ifinfo(struct igmp_ifinfo *igi)
+{
+
+ printf("\t");
+ switch (igi->igi_version) {
+ case IGMP_VERSION_1:
+ case IGMP_VERSION_2:
+ case IGMP_VERSION_3:
+ printf("igmpv%d", igi->igi_version);
+ break;
+ default:
+ printf("igmpv?(%d)", igi->igi_version);
+ break;
+ }
+ if (igi->igi_flags)
+ printb(" flags", igi->igi_flags, "\020\1SILENT\2LOOPBACK");
+ if (igi->igi_version == IGMP_VERSION_3) {
+ printf(" rv %u qi %u qri %u uri %u",
+ igi->igi_rv, igi->igi_qi, igi->igi_qri, igi->igi_uri);
+ }
+ if (vflag >= 2) {
+ printf(" v1timer %u v2timer %u v3timer %u",
+ igi->igi_v1_timer, igi->igi_v2_timer, igi->igi_v3_timer);
+ }
+ printf("\n");
+}
+
+static const char * const inm_modes[] = {
+ "undefined",
+ "include",
+ "exclude",
+};
+
+static const char *
+inm_mode(u_int mode)
+{
+
+ if (mode >= MCAST_UNDEFINED && mode <= MCAST_EXCLUDE)
+ return (inm_modes[mode]);
+ return (NULL);
+}
+
+#endif /* INET */
+
+#ifdef WITH_KVM
+
+static int
+ifmcstat_kvm(const char *kernel, const char *core)
+{
+ char buf[_POSIX2_LINE_MAX], ifname[IFNAMSIZ];
+ struct ifnet *ifp, *nifp, ifnet;
+
+ if ((kvmd = kvm_openfiles(kernel, core, NULL, O_RDONLY, buf)) ==
+ NULL) {
+ perror("kvm_openfiles");
+ return (-1);
+ }
+ if (kvm_nlist(kvmd, nl) < 0) {
+ perror("kvm_nlist");
+ return (-1);
+ }
+ if (nl[N_IFNET].n_value == 0) {
+ printf("symbol %s not found\n", nl[N_IFNET].n_name);
+ return (-1);
+ }
+ KREAD(nl[N_IFNET].n_value, &ifp, struct ifnet *);
+ while (ifp) {
+ KREAD(ifp, &ifnet, struct ifnet);
+ nifp = ifnet.if_link.tqe_next;
+ if (ifindex && ifindex != ifnet.if_index)
+ goto next;
+
+ printf("%s:\n", if_indextoname(ifnet.if_index, ifname));
+#ifdef INET
+ if_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
+#endif
+#ifdef INET6
+ if6_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
+#endif
+ if (vflag)
+ ll_addrlist(TAILQ_FIRST(&ifnet.if_addrhead));
+ next:
+ ifp = nifp;
+ }
+
+ return (0);
+}
+
+static void
+kread(u_long addr, void *buf, int len)
+{
+
+ if (kvm_read(kvmd, addr, buf, len) != len) {
+ perror("kvm_read");
+ exit(EX_OSERR);
+ }
+}
+
+static void
+ll_addrlist(struct ifaddr *ifap)
+{
+ char addrbuf[NI_MAXHOST];
+ struct ifaddr ifa;
+ struct sockaddr sa;
+ struct sockaddr_dl sdl;
+ struct ifaddr *ifap0;
+
+ if (af && af != AF_LINK)
+ return;
+
+ ifap0 = ifap;
+ while (ifap) {
+ KREAD(ifap, &ifa, struct ifaddr);
+ if (ifa.ifa_addr == NULL)
+ goto nextifap;
+ KREAD(ifa.ifa_addr, &sa, struct sockaddr);
+ if (sa.sa_family != PF_LINK)
+ goto nextifap;
+ KREAD(ifa.ifa_addr, &sdl, struct sockaddr_dl);
+ if (sdl.sdl_alen == 0)
+ goto nextifap;
+ addrbuf[0] = '\0';
+ getnameinfo((struct sockaddr *)&sdl, sdl.sdl_len,
+ addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
+ printf("\tlink %s\n", addrbuf);
+ nextifap:
+ ifap = ifa.ifa_link.tqe_next;
+ }
+ if (ifap0) {
+ struct ifnet ifnet;
+ struct ifmultiaddr ifm, *ifmp = 0;
+
+ KREAD(ifap0, &ifa, struct ifaddr);
+ KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
+ if (TAILQ_FIRST(&ifnet.if_multiaddrs))
+ ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
+ while (ifmp) {
+ KREAD(ifmp, &ifm, struct ifmultiaddr);
+ if (ifm.ifma_addr == NULL)
+ goto nextmulti;
+ KREAD(ifm.ifma_addr, &sa, struct sockaddr);
+ if (sa.sa_family != AF_LINK)
+ goto nextmulti;
+ KREAD(ifm.ifma_addr, &sdl, struct sockaddr_dl);
+ addrbuf[0] = '\0';
+ getnameinfo((struct sockaddr *)&sdl,
+ sdl.sdl_len, addrbuf, sizeof(addrbuf),
+ NULL, 0, NI_NUMERICHOST);
+ printf("\t\tgroup %s refcnt %d\n",
+ addrbuf, ifm.ifma_refcount);
+ nextmulti:
+ ifmp = TAILQ_NEXT(&ifm, ifma_link);
+ }
+ }
+}
+
+#ifdef INET6
+
+static void
+if6_addrlist(struct ifaddr *ifap)
+{
+ struct ifnet ifnet;
+ struct ifaddr ifa;
+ struct sockaddr sa;
+ struct in6_ifaddr if6a;
+ struct ifaddr *ifap0;
+
+ if (af && af != AF_INET6)
+ return;
+ ifap0 = ifap;
+ while (ifap) {
+ KREAD(ifap, &ifa, struct ifaddr);
+ if (ifa.ifa_addr == NULL)
+ goto nextifap;
+ KREAD(ifa.ifa_addr, &sa, struct sockaddr);
+ if (sa.sa_family != PF_INET6)
+ goto nextifap;
+ KREAD(ifap, &if6a, struct in6_ifaddr);
+ printf("\tinet6 %s\n", inet6_n2a(&if6a.ia_addr.sin6_addr,
+ if6a.ia_addr.sin6_scope_id));
+ /*
+ * Print per-link MLD information, if available.
+ */
+ if (ifa.ifa_ifp != NULL) {
+ struct in6_ifextra ie;
+ struct mld_ifinfo mli;
+
+ KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
+ KREAD(ifnet.if_afdata[AF_INET6], &ie,
+ struct in6_ifextra);
+ if (ie.mld_ifinfo != NULL) {
+ KREAD(ie.mld_ifinfo, &mli, struct mld_ifinfo);
+ in6_ifinfo(&mli);
+ }
+ }
+ nextifap:
+ ifap = ifa.ifa_link.tqe_next;
+ }
+ if (ifap0) {
+ struct ifnet ifnet;
+ struct ifmultiaddr ifm, *ifmp = 0;
+ struct sockaddr_dl sdl;
+
+ KREAD(ifap0, &ifa, struct ifaddr);
+ KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
+ if (TAILQ_FIRST(&ifnet.if_multiaddrs))
+ ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
+ while (ifmp) {
+ KREAD(ifmp, &ifm, struct ifmultiaddr);
+ if (ifm.ifma_addr == NULL)
+ goto nextmulti;
+ KREAD(ifm.ifma_addr, &sa, struct sockaddr);
+ if (sa.sa_family != AF_INET6)
+ goto nextmulti;
+ (void)in6_multientry((struct in6_multi *)
+ ifm.ifma_protospec);
+ if (ifm.ifma_lladdr == 0)
+ goto nextmulti;
+ KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
+ printf("\t\t\tmcast-macaddr %s refcnt %d\n",
+ ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
+ ifm.ifma_refcount);
+ nextmulti:
+ ifmp = TAILQ_NEXT(&ifm, ifma_link);
+ }
+ }
+}
+
+static struct in6_multi *
+in6_multientry(struct in6_multi *mc)
+{
+ struct in6_multi multi;
+
+ KREAD(mc, &multi, struct in6_multi);
+ printf("\t\tgroup %s", inet6_n2a(&multi.in6m_addr, 0));
+ printf(" refcnt %u\n", multi.in6m_refcount);
+
+ return (multi.in6m_entry.le_next);
+}
+
+#endif /* INET6 */
+
+#ifdef INET
+
+static void
+if_addrlist(struct ifaddr *ifap)
+{
+ struct ifaddr ifa;
+ struct ifnet ifnet;
+ struct sockaddr sa;
+ struct in_ifaddr ia;
+ struct ifaddr *ifap0;
+
+ if (af && af != AF_INET)
+ return;
+ ifap0 = ifap;
+ while (ifap) {
+ KREAD(ifap, &ifa, struct ifaddr);
+ if (ifa.ifa_addr == NULL)
+ goto nextifap;
+ KREAD(ifa.ifa_addr, &sa, struct sockaddr);
+ if (sa.sa_family != PF_INET)
+ goto nextifap;
+ KREAD(ifap, &ia, struct in_ifaddr);
+ printf("\tinet %s\n", inet_ntoa(ia.ia_addr.sin_addr));
+ /*
+ * Print per-link IGMP information, if available.
+ */
+ if (ifa.ifa_ifp != NULL) {
+ struct in_ifinfo ii;
+ struct igmp_ifinfo igi;
+
+ KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
+ KREAD(ifnet.if_afdata[AF_INET], &ii, struct in_ifinfo);
+ if (ii.ii_igmp != NULL) {
+ KREAD(ii.ii_igmp, &igi, struct igmp_ifinfo);
+ in_ifinfo(&igi);
+ }
+ }
+ nextifap:
+ ifap = ifa.ifa_link.tqe_next;
+ }
+ if (ifap0) {
+ struct ifmultiaddr ifm, *ifmp = 0;
+ struct sockaddr_dl sdl;
+
+ KREAD(ifap0, &ifa, struct ifaddr);
+ KREAD(ifa.ifa_ifp, &ifnet, struct ifnet);
+ if (TAILQ_FIRST(&ifnet.if_multiaddrs))
+ ifmp = TAILQ_FIRST(&ifnet.if_multiaddrs);
+ while (ifmp) {
+ KREAD(ifmp, &ifm, struct ifmultiaddr);
+ if (ifm.ifma_addr == NULL)
+ goto nextmulti;
+ KREAD(ifm.ifma_addr, &sa, struct sockaddr);
+ if (sa.sa_family != AF_INET)
+ goto nextmulti;
+ (void)in_multientry((struct in_multi *)
+ ifm.ifma_protospec);
+ if (ifm.ifma_lladdr == 0)
+ goto nextmulti;
+ KREAD(ifm.ifma_lladdr, &sdl, struct sockaddr_dl);
+ printf("\t\t\tmcast-macaddr %s refcnt %d\n",
+ ether_ntoa((struct ether_addr *)LLADDR(&sdl)),
+ ifm.ifma_refcount);
+ nextmulti:
+ ifmp = TAILQ_NEXT(&ifm, ifma_link);
+ }
+ }
+}
+
+static const char *inm_states[] = {
+ "not-member",
+ "silent",
+ "idle",
+ "lazy",
+ "sleeping",
+ "awakening",
+ "query-pending",
+ "sg-query-pending",
+ "leaving"
+};
+
+static const char *
+inm_state(u_int state)
+{
+
+ if (state >= IGMP_NOT_MEMBER && state <= IGMP_LEAVING_MEMBER)
+ return (inm_states[state]);
+ return (NULL);
+}
+
+#if 0
+static struct ip_msource *
+ims_min_kvm(struct in_multi *pinm)
+{
+ struct ip_msource ims0;
+ struct ip_msource *tmp, *parent;
+
+ parent = NULL;
+ tmp = RB_ROOT(&pinm->inm_srcs);
+ while (tmp) {
+ parent = tmp;
+ KREAD(tmp, &ims0, struct ip_msource);
+ tmp = RB_LEFT(&ims0, ims_link);
+ }
+ return (parent); /* kva */
+}
+
+/* XXX This routine is buggy. See RB_NEXT in sys/tree.h. */
+static struct ip_msource *
+ims_next_kvm(struct ip_msource *ims)
+{
+ struct ip_msource ims0, ims1;
+ struct ip_msource *tmp;
+
+ KREAD(ims, &ims0, struct ip_msource);
+ if (RB_RIGHT(&ims0, ims_link)) {
+ ims = RB_RIGHT(&ims0, ims_link);
+ KREAD(ims, &ims1, struct ip_msource);
+ while ((tmp = RB_LEFT(&ims1, ims_link))) {
+ KREAD(tmp, &ims0, struct ip_msource);
+ ims = RB_LEFT(&ims0, ims_link);
+ }
+ } else {
+ tmp = RB_PARENT(&ims0, ims_link);
+ if (tmp) {
+ KREAD(tmp, &ims1, struct ip_msource);
+ if (ims == RB_LEFT(&ims1, ims_link))
+ ims = tmp;
+ } else {
+ while ((tmp = RB_PARENT(&ims0, ims_link))) {
+ KREAD(tmp, &ims1, struct ip_msource);
+ if (ims == RB_RIGHT(&ims1, ims_link)) {
+ ims = tmp;
+ KREAD(ims, &ims0, struct ip_msource);
+ } else
+ break;
+ }
+ ims = RB_PARENT(&ims0, ims_link);
+ }
+ }
+ return (ims); /* kva */
+}
+
+static void
+inm_print_sources_kvm(struct in_multi *pinm)
+{
+ struct ip_msource ims0;
+ struct ip_msource *ims;
+ struct in_addr src;
+ int cnt;
+ uint8_t fmode;
+
+ cnt = 0;
+ fmode = pinm->inm_st[1].iss_fmode;
+ if (fmode == MCAST_UNDEFINED)
+ return;
+ for (ims = ims_min_kvm(pinm); ims != NULL; ims = ims_next_kvm(ims)) {
+ if (cnt == 0)
+ printf(" srcs ");
+ KREAD(ims, &ims0, struct ip_msource);
+ /* Only print sources in-mode at t1. */
+ if (fmode != ims_get_mode(pinm, ims, 1))
+ continue;
+ src.s_addr = htonl(ims0.ims_haddr);
+ printf("%s%s", (cnt++ == 0 ? "" : ","), inet_ntoa(src));
+ }
+}
+#endif
+
+static struct in_multi *
+in_multientry(struct in_multi *pinm)
+{
+ struct in_multi inm;
+ const char *state, *mode;
+
+ KREAD(pinm, &inm, struct in_multi);
+ printf("\t\tgroup %s", inet_ntoa(inm.inm_addr));
+ printf(" refcnt %u", inm.inm_refcount);
+
+ state = inm_state(inm.inm_state);
+ if (state)
+ printf(" state %s", state);
+ else
+ printf(" state (%d)", inm.inm_state);
+
+ mode = inm_mode(inm.inm_st[1].iss_fmode);
+ if (mode)
+ printf(" mode %s", mode);
+ else
+ printf(" mode (%d)", inm.inm_st[1].iss_fmode);
+
+ if (vflag >= 2) {
+ printf(" asm %u ex %u in %u rec %u",
+ (u_int)inm.inm_st[1].iss_asm,
+ (u_int)inm.inm_st[1].iss_ex,
+ (u_int)inm.inm_st[1].iss_in,
+ (u_int)inm.inm_st[1].iss_rec);
+ }
+
+#if 0
+ /* Buggy. */
+ if (vflag)
+ inm_print_sources_kvm(&inm);
+#endif
+
+ printf("\n");
+ return (NULL);
+}
+
+#endif /* INET */
+
+#endif /* WITH_KVM */
+
+#ifdef INET6
+
+static void
+in6_ifinfo(struct mld_ifinfo *mli)
+{
+
+ printf("\t");
+ switch (mli->mli_version) {
+ case MLD_VERSION_1:
+ case MLD_VERSION_2:
+ printf("mldv%d", mli->mli_version);
+ break;
+ default:
+ printf("mldv?(%d)", mli->mli_version);
+ break;
+ }
+ if (mli->mli_flags)
+ printb(" flags", mli->mli_flags, "\020\1SILENT\2USEALLOW");
+ if (mli->mli_version == MLD_VERSION_2) {
+ printf(" rv %u qi %u qri %u uri %u",
+ mli->mli_rv, mli->mli_qi, mli->mli_qri, mli->mli_uri);
+ }
+ if (vflag >= 2) {
+ printf(" v1timer %u v2timer %u", mli->mli_v1_timer,
+ mli->mli_v2_timer);
+ }
+ printf("\n");
+}
+
+static const char *
+inet6_n2a(struct in6_addr *p, uint32_t scope_id)
+{
+ static char buf[NI_MAXHOST];
+ struct sockaddr_in6 sin6;
+ const int niflags = NI_NUMERICHOST;
+
+ memset(&sin6, 0, sizeof(sin6));
+ sin6.sin6_family = AF_INET6;
+ sin6.sin6_len = sizeof(struct sockaddr_in6);
+ sin6.sin6_addr = *p;
+ sin6.sin6_scope_id = scope_id;
+ if (getnameinfo((struct sockaddr *)&sin6, sin6.sin6_len,
+ buf, sizeof(buf), NULL, 0, niflags) == 0) {
+ return (buf);
+ } else {
+ return ("(invalid)");
+ }
+}
+#endif /* INET6 */
+
+#ifdef INET
+/*
+ * Retrieve per-group source filter mode and lists via sysctl.
+ */
+static void
+inm_print_sources_sysctl(uint32_t ifindex, struct in_addr gina)
+{
+#define MAX_SYSCTL_TRY 5
+ int mib[7];
+ int ntry = 0;
+ size_t mibsize;
+ size_t len;
+ size_t needed;
+ size_t cnt;
+ int i;
+ char *buf;
+ struct in_addr *pina;
+ uint32_t *p;
+ uint32_t fmode;
+ const char *modestr;
+
+ mibsize = nitems(mib);
+ if (sysctlnametomib("net.inet.ip.mcast.filters", mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ return;
+ }
+
+ needed = 0;
+ mib[5] = ifindex;
+ mib[6] = gina.s_addr; /* 32 bits wide */
+ mibsize = nitems(mib);
+ do {
+ if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
+ perror("sysctl net.inet.ip.mcast.filters");
+ return;
+ }
+ if ((buf = malloc(needed)) == NULL) {
+ perror("malloc");
+ return;
+ }
+ if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ perror("sysctl");
+ goto out_free;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ len = needed;
+ if (len < sizeof(uint32_t)) {
+ perror("sysctl");
+ goto out_free;
+ }
+
+ p = (uint32_t *)buf;
+ fmode = *p++;
+ len -= sizeof(uint32_t);
+
+ modestr = inm_mode(fmode);
+ if (modestr)
+ printf(" mode %s", modestr);
+ else
+ printf(" mode (%u)", fmode);
+
+ if (vflag == 0)
+ goto out_free;
+
+ cnt = len / sizeof(struct in_addr);
+ pina = (struct in_addr *)p;
+
+ for (i = 0; i < cnt; i++) {
+ if (i == 0)
+ printf(" srcs ");
+ fprintf(stdout, "%s%s", (i == 0 ? "" : ","),
+ inet_ntoa(*pina++));
+ len -= sizeof(struct in_addr);
+ }
+ if (len > 0) {
+ fprintf(stderr, "warning: %u trailing bytes from %s\n",
+ (unsigned int)len, "net.inet.ip.mcast.filters");
+ }
+
+out_free:
+ free(buf);
+#undef MAX_SYSCTL_TRY
+}
+
+#endif /* INET */
+
+#ifdef INET6
+/*
+ * Retrieve MLD per-group source filter mode and lists via sysctl.
+ *
+ * Note: The 128-bit IPv6 group address needs to be segmented into
+ * 32-bit pieces for marshaling to sysctl. So the MIB name ends
+ * up looking like this:
+ * a.b.c.d.e.ifindex.g[0].g[1].g[2].g[3]
+ * Assumes that pgroup originated from the kernel, so its components
+ * are already in network-byte order.
+ */
+static void
+in6m_print_sources_sysctl(uint32_t ifindex, struct in6_addr *pgroup)
+{
+#define MAX_SYSCTL_TRY 5
+ char addrbuf[INET6_ADDRSTRLEN];
+ int mib[10];
+ int ntry = 0;
+ int *pi;
+ size_t mibsize;
+ size_t len;
+ size_t needed;
+ size_t cnt;
+ int i;
+ char *buf;
+ struct in6_addr *pina;
+ uint32_t *p;
+ uint32_t fmode;
+ const char *modestr;
+
+ mibsize = nitems(mib);
+ if (sysctlnametomib("net.inet6.ip6.mcast.filters", mib,
+ &mibsize) == -1) {
+ perror("sysctlnametomib");
+ return;
+ }
+
+ needed = 0;
+ mib[5] = ifindex;
+ pi = (int *)pgroup;
+ for (i = 0; i < 4; i++)
+ mib[6 + i] = *pi++;
+
+ mibsize = nitems(mib);
+ do {
+ if (sysctl(mib, mibsize, NULL, &needed, NULL, 0) == -1) {
+ perror("sysctl net.inet6.ip6.mcast.filters");
+ return;
+ }
+ if ((buf = malloc(needed)) == NULL) {
+ perror("malloc");
+ return;
+ }
+ if (sysctl(mib, mibsize, buf, &needed, NULL, 0) == -1) {
+ if (errno != ENOMEM || ++ntry >= MAX_SYSCTL_TRY) {
+ perror("sysctl");
+ goto out_free;
+ }
+ free(buf);
+ buf = NULL;
+ }
+ } while (buf == NULL);
+
+ len = needed;
+ if (len < sizeof(uint32_t)) {
+ perror("sysctl");
+ goto out_free;
+ }
+
+ p = (uint32_t *)buf;
+ fmode = *p++;
+ len -= sizeof(uint32_t);
+
+ modestr = inm_mode(fmode);
+ if (modestr)
+ printf(" mode %s", modestr);
+ else
+ printf(" mode (%u)", fmode);
+
+ if (vflag == 0)
+ goto out_free;
+
+ cnt = len / sizeof(struct in6_addr);
+ pina = (struct in6_addr *)p;
+
+ for (i = 0; i < cnt; i++) {
+ if (i == 0)
+ printf(" srcs ");
+ inet_ntop(AF_INET6, (const char *)pina++, addrbuf,
+ INET6_ADDRSTRLEN);
+ fprintf(stdout, "%s%s", (i == 0 ? "" : ","), addrbuf);
+ len -= sizeof(struct in6_addr);
+ }
+ if (len > 0) {
+ fprintf(stderr, "warning: %u trailing bytes from %s\n",
+ (unsigned int)len, "net.inet6.ip6.mcast.filters");
+ }
+
+out_free:
+ free(buf);
+#undef MAX_SYSCTL_TRY
+}
+#endif /* INET6 */
+
+static int
+ifmcstat_getifmaddrs(void)
+{
+ char thisifname[IFNAMSIZ];
+ char addrbuf[NI_MAXHOST];
+ struct ifaddrs *ifap, *ifa;
+ struct ifmaddrs *ifmap, *ifma;
+ sockunion_t lastifasa;
+ sockunion_t *psa, *pgsa, *pllsa, *pifasa;
+ char *pcolon;
+ char *pafname;
+ uint32_t lastifindex, thisifindex;
+ int error;
+
+ error = 0;
+ ifap = NULL;
+ ifmap = NULL;
+ lastifindex = 0;
+ thisifindex = 0;
+ lastifasa.ss.ss_family = AF_UNSPEC;
+
+ if (getifaddrs(&ifap) != 0) {
+ warn("getifmaddrs");
+ return (-1);
+ }
+
+ if (getifmaddrs(&ifmap) != 0) {
+ warn("getifmaddrs");
+ error = -1;
+ goto out;
+ }
+
+ for (ifma = ifmap; ifma; ifma = ifma->ifma_next) {
+ error = 0;
+ if (ifma->ifma_name == NULL || ifma->ifma_addr == NULL)
+ continue;
+
+ psa = (sockunion_t *)ifma->ifma_name;
+ if (psa->sa.sa_family != AF_LINK) {
+ fprintf(stderr,
+ "WARNING: Kernel returned invalid data.\n");
+ error = -1;
+ break;
+ }
+
+ /* Filter on interface name. */
+ thisifindex = psa->sdl.sdl_index;
+ if (ifindex != 0 && thisifindex != ifindex)
+ continue;
+
+ /* Filter on address family. */
+ pgsa = (sockunion_t *)ifma->ifma_addr;
+ if (af != 0 && pgsa->sa.sa_family != af)
+ continue;
+
+ strlcpy(thisifname, link_ntoa(&psa->sdl), IFNAMSIZ);
+ pcolon = strchr(thisifname, ':');
+ if (pcolon)
+ *pcolon = '\0';
+
+ /* Only print the banner for the first ifmaddrs entry. */
+ if (lastifindex == 0 || lastifindex != thisifindex) {
+ lastifindex = thisifindex;
+ fprintf(stdout, "%s:\n", thisifname);
+ }
+
+ /*
+ * Currently, multicast joins only take place on the
+ * primary IPv4 address, and only on the link-local IPv6
+ * address, as per IGMPv2/3 and MLDv1/2 semantics.
+ * Therefore, we only look up the primary address on
+ * the first pass.
+ */
+ pifasa = NULL;
+ for (ifa = ifap; ifa; ifa = ifa->ifa_next) {
+ if ((strcmp(ifa->ifa_name, thisifname) != 0) ||
+ (ifa->ifa_addr == NULL) ||
+ (ifa->ifa_addr->sa_family != pgsa->sa.sa_family))
+ continue;
+ /*
+ * For AF_INET6 only the link-local address should
+ * be returned. If built without IPv6 support,
+ * skip this address entirely.
+ */
+ pifasa = (sockunion_t *)ifa->ifa_addr;
+ if (pifasa->sa.sa_family == AF_INET6
+#ifdef INET6
+ && !IN6_IS_ADDR_LINKLOCAL(&pifasa->sin6.sin6_addr)
+#endif
+ ) {
+ pifasa = NULL;
+ continue;
+ }
+ break;
+ }
+ if (pifasa == NULL)
+ continue; /* primary address not found */
+
+ if (!vflag && pifasa->sa.sa_family == AF_LINK)
+ continue;
+
+ /* Parse and print primary address, if not already printed. */
+ if (lastifasa.ss.ss_family == AF_UNSPEC ||
+ ((lastifasa.ss.ss_family == AF_LINK &&
+ !sa_dl_equal(&lastifasa.sa, &pifasa->sa)) ||
+ !sa_equal(&lastifasa.sa, &pifasa->sa))) {
+
+ switch (pifasa->sa.sa_family) {
+ case AF_INET:
+ pafname = "inet";
+ break;
+ case AF_INET6:
+ pafname = "inet6";
+ break;
+ case AF_LINK:
+ pafname = "link";
+ break;
+ default:
+ pafname = "unknown";
+ break;
+ }
+
+ switch (pifasa->sa.sa_family) {
+ case AF_INET6:
+#ifdef INET6
+ {
+ const char *p =
+ inet6_n2a(&pifasa->sin6.sin6_addr,
+ pifasa->sin6.sin6_scope_id);
+ strlcpy(addrbuf, p, sizeof(addrbuf));
+ break;
+ }
+#else
+ /* FALLTHROUGH */
+#endif
+ case AF_INET:
+ case AF_LINK:
+ error = getnameinfo(&pifasa->sa,
+ pifasa->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0,
+ NI_NUMERICHOST);
+ if (error)
+ perror("getnameinfo");
+ break;
+ default:
+ addrbuf[0] = '\0';
+ break;
+ }
+
+ fprintf(stdout, "\t%s %s", pafname, addrbuf);
+#ifdef INET6
+ if (pifasa->sa.sa_family == AF_INET6 &&
+ pifasa->sin6.sin6_scope_id)
+ fprintf(stdout, " scopeid 0x%x",
+ pifasa->sin6.sin6_scope_id);
+#endif
+ fprintf(stdout, "\n");
+#ifdef INET
+ /*
+ * Print per-link IGMP information, if available.
+ */
+ if (pifasa->sa.sa_family == AF_INET) {
+ struct igmp_ifinfo igi;
+ size_t mibsize, len;
+ int mib[5];
+
+ mibsize = nitems(mib);
+ if (sysctlnametomib("net.inet.igmp.ifinfo",
+ mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ goto next_ifnet;
+ }
+ mib[mibsize] = thisifindex;
+ len = sizeof(struct igmp_ifinfo);
+ if (sysctl(mib, mibsize + 1, &igi, &len, NULL,
+ 0) == -1) {
+ perror("sysctl net.inet.igmp.ifinfo");
+ goto next_ifnet;
+ }
+ in_ifinfo(&igi);
+ }
+#endif /* INET */
+#ifdef INET6
+ /*
+ * Print per-link MLD information, if available.
+ */
+ if (pifasa->sa.sa_family == AF_INET6) {
+ struct mld_ifinfo mli;
+ size_t mibsize, len;
+ int mib[5];
+
+ mibsize = nitems(mib);
+ if (sysctlnametomib("net.inet6.mld.ifinfo",
+ mib, &mibsize) == -1) {
+ perror("sysctlnametomib");
+ goto next_ifnet;
+ }
+ mib[mibsize] = thisifindex;
+ len = sizeof(struct mld_ifinfo);
+ if (sysctl(mib, mibsize + 1, &mli, &len, NULL,
+ 0) == -1) {
+ perror("sysctl net.inet6.mld.ifinfo");
+ goto next_ifnet;
+ }
+ in6_ifinfo(&mli);
+ }
+#endif /* INET6 */
+#if defined(INET) || defined(INET6)
+next_ifnet:
+#endif
+ lastifasa = *pifasa;
+ }
+
+ /* Print this group address. */
+#ifdef INET6
+ if (pgsa->sa.sa_family == AF_INET6) {
+ const char *p = inet6_n2a(&pgsa->sin6.sin6_addr,
+ pgsa->sin6.sin6_scope_id);
+ strlcpy(addrbuf, p, sizeof(addrbuf));
+ } else
+#endif
+ {
+ error = getnameinfo(&pgsa->sa, pgsa->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
+ if (error)
+ perror("getnameinfo");
+ }
+
+ fprintf(stdout, "\t\tgroup %s", addrbuf);
+#ifdef INET6
+ if (pgsa->sa.sa_family == AF_INET6 &&
+ pgsa->sin6.sin6_scope_id)
+ fprintf(stdout, " scopeid 0x%x",
+ pgsa->sin6.sin6_scope_id);
+#endif
+#ifdef INET
+ if (pgsa->sa.sa_family == AF_INET) {
+ inm_print_sources_sysctl(thisifindex,
+ pgsa->sin.sin_addr);
+ }
+#endif
+#ifdef INET6
+ if (pgsa->sa.sa_family == AF_INET6) {
+ in6m_print_sources_sysctl(thisifindex,
+ &pgsa->sin6.sin6_addr);
+ }
+#endif
+ fprintf(stdout, "\n");
+
+ /* Link-layer mapping, if present. */
+ pllsa = (sockunion_t *)ifma->ifma_lladdr;
+ if (pllsa != NULL) {
+ error = getnameinfo(&pllsa->sa, pllsa->sa.sa_len,
+ addrbuf, sizeof(addrbuf), NULL, 0, NI_NUMERICHOST);
+ fprintf(stdout, "\t\t\tmcast-macaddr %s\n", addrbuf);
+ }
+ }
+out:
+ if (ifmap != NULL)
+ freeifmaddrs(ifmap);
+ if (ifap != NULL)
+ freeifaddrs(ifap);
+
+ return (error);
+}
diff --git a/freebsd/usr.sbin/ifmcstat/printb.c b/freebsd/usr.sbin/ifmcstat/printb.c
new file mode 100644
index 00000000..2c979951
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/printb.c
@@ -0,0 +1,75 @@
+#include <machine/rtems-bsd-user-space.h>
+
+#ifdef __rtems__
+#include "rtems-bsd-ifmcstat-namespace.h"
+#include "rtems-bsd-ifmcstat-printb-data.h"
+#endif /* __rtems__ */
+
+/*-
+ * SPDX-License-Identifier: BSD-3-Clause
+ *
+ * Copyright (c) 1983, 1993
+ * The Regents of the University of California. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of the University nor the names of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
+ * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
+ * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
+ * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
+ * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
+ * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
+ * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ */
+
+#include <sys/cdefs.h>
+__FBSDID("$FreeBSD$");
+
+#include <assert.h>
+#include <stdio.h>
+
+/*
+ * Print a value a la the %b format of the kernel's printf
+ */
+void
+printb(const char *s, unsigned int v, const char *bits)
+{
+ int i, any = 0;
+ char c;
+
+ assert(bits != NULL);
+ if (*bits == 8)
+ printf("%s=%o", s, v);
+ else
+ printf("%s=%x", s, v);
+ bits++;
+ if (bits) {
+ putchar('<');
+ while ((i = *bits++) != '\0') {
+ if (v & (1 << (i-1))) {
+ if (any)
+ putchar(',');
+ any = 1;
+ for (; (c = *bits) > 32; bits++)
+ putchar(c);
+ } else
+ for (; *bits > 32; bits++)
+ ;
+ }
+ putchar('>');
+ }
+}
diff --git a/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-data.h b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-data.h
new file mode 100644
index 00000000..e94df9c0
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-data.h
@@ -0,0 +1,4 @@
+/* generated by userspace-header-gen.py */
+#include <rtems/linkersets.h>
+/* ifmcstat.c */
+/* printb.c */
diff --git a/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-ifmcstat-data.h b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-ifmcstat-data.h
new file mode 100644
index 00000000..39287947
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-ifmcstat-data.h
@@ -0,0 +1,7 @@
+/* generated by userspace-header-gen.py */
+#include <rtems/linkersets.h>
+#include "rtems-bsd-ifmcstat-data.h"
+/* ifmcstat.c */
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ifmcstat, static int af);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ifmcstat, static int vflag);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_ifmcstat, static uint32_t ifindex);
diff --git a/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-namespace.h b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-namespace.h
new file mode 100644
index 00000000..78414818
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-namespace.h
@@ -0,0 +1,5 @@
+/* generated by userspace-header-gen.py */
+/* ifmcstat.c */
+#define main _bsd_ifmcstat_main
+/* printb.c */
+#define printb _bsd_ifmcstat_printb
diff --git a/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-printb-data.h b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-printb-data.h
new file mode 100644
index 00000000..3f74bd60
--- /dev/null
+++ b/freebsd/usr.sbin/ifmcstat/rtems-bsd-ifmcstat-printb-data.h
@@ -0,0 +1,4 @@
+/* generated by userspace-header-gen.py */
+#include <rtems/linkersets.h>
+#include "rtems-bsd-ifmcstat-data.h"
+/* printb.c */
diff --git a/ipsec-tools/src/libipsec/pfkey.c b/ipsec-tools/src/libipsec/pfkey.c
index a621be12..385a21a9 100644
--- a/ipsec-tools/src/libipsec/pfkey.c
+++ b/ipsec-tools/src/libipsec/pfkey.c
@@ -1,5 +1,12 @@
#include <machine/rtems-bsd-user-space.h>
+#ifdef __rtems__
+/* Only need socket from rtems-bsd-program wrappers! */
+int
+rtems_bsd_program_socket(int domain, int type, int protocol);
+#define socket(domain, type, protocol) \
+ rtems_bsd_program_socket(domain, type, protocol)
+#endif /* __rtems__ */
/* $NetBSD: pfkey.c,v 1.21.2.1 2011/11/14 13:25:06 tteras Exp $ */
/* $KAME: pfkey.c,v 1.47 2003/10/02 19:52:12 itojun Exp $ */
diff --git a/ipsec-tools/src/racoon/rtems-bsd-racoon-session-data.h b/ipsec-tools/src/racoon/rtems-bsd-racoon-session-data.h
index 9a1b03f1..196107a3 100644
--- a/ipsec-tools/src/racoon/rtems-bsd-racoon-session-data.h
+++ b/ipsec-tools/src/racoon/rtems-bsd-racoon-session-data.h
@@ -2,11 +2,11 @@
#include <rtems/linkersets.h>
#include "rtems-bsd-racoon-data.h"
/* session.c */
-RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static _types_fd_set active_mask);
-RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static _types_fd_set preset_mask);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static _types_fd_set *allocated_active_mask);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static _types_fd_set *allocated_preset_mask);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static int nfds);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static int signals[]);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static sig_atomic_t volatile volatile sigreq[]);
-RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static struct fd_monitor fd_monitors[]);
+RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static struct fd_monitor *allocated_fd_monitors);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static struct fd_monitor_list fd_monitor_tree[]);
RTEMS_LINKER_RWSET_CONTENT(bsd_prog_racoon, static struct sched scflushsa);
diff --git a/ipsec-tools/src/racoon/session.c b/ipsec-tools/src/racoon/session.c
index 65124c15..77e4f6f6 100644
--- a/ipsec-tools/src/racoon/session.c
+++ b/ipsec-tools/src/racoon/session.c
@@ -65,6 +65,10 @@
#include <sys/stat.h>
#include <paths.h>
#include <err.h>
+#ifdef __rtems__
+#include <sys/param.h>
+#include <rtems/libio_.h>
+#endif /* __rtems__ */
#include <netinet/in.h>
#include <resolv.h>
@@ -123,8 +127,16 @@ static void check_sigreq __P((void));
static void check_flushsa __P((void));
static int close_sockets __P((void));
+#ifndef __rtems__
static fd_set preset_mask, active_mask;
static struct fd_monitor fd_monitors[FD_SETSIZE];
+#else /* __rtems__ */
+static fd_set *allocated_preset_mask, *allocated_active_mask;
+static struct fd_monitor *allocated_fd_monitors;
+#define preset_mask (*allocated_preset_mask)
+#define active_mask (*allocated_active_mask)
+#define fd_monitors (allocated_fd_monitors)
+#endif /* __rtems__ */
static TAILQ_HEAD(fd_monitor_list, fd_monitor) fd_monitor_tree[NUM_PRIORITIES];
static int nfds = 0;
@@ -134,7 +146,11 @@ static struct sched scflushsa = SCHED_INITIALIZER();
void
monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
{
+#ifndef __rtems__
if (fd < 0 || fd >= FD_SETSIZE) {
+#else /* __rtems__ */
+ if (fd < 0 || fd >= rtems_libio_number_iops) {
+#endif /* __rtems__ */
plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
exit(1);
}
@@ -158,7 +174,11 @@ monitor_fd(int fd, int (*callback)(void *, int), void *ctx, int priority)
void
unmonitor_fd(int fd)
{
+#ifndef __rtems__
if (fd < 0 || fd >= FD_SETSIZE) {
+#else /* __rtems__ */
+ if (fd < 0 || fd >= rtems_libio_number_iops) {
+#endif /* __rtems__ */
plog(LLV_ERROR, LOCATION, NULL, "fd_set overrun");
exit(1);
}
@@ -186,7 +206,24 @@ session(void)
struct fd_monitor *fdm;
nfds = 0;
+#ifndef __rtems__
FD_ZERO(&preset_mask);
+#else /* __rtems__ */
+ size_t allocated_mask_size = sizeof(fd_set) *
+ howmany(rtems_libio_number_iops, sizeof(fd_set) * 8);
+ allocated_preset_mask = calloc(sizeof(fd_set),
+ howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
+ if (allocated_preset_mask == NULL)
+ errx(1, "failed to allocate preset_mask");
+ allocated_active_mask = calloc(sizeof(fd_set),
+ howmany(rtems_libio_number_iops, sizeof(fd_set) * 8));
+ if (allocated_active_mask == NULL)
+ errx(1, "failed to allocate active_mask");
+ allocated_fd_monitors = calloc(
+ rtems_libio_number_iops, sizeof(struct fd_monitor));
+ if (allocated_fd_monitors == NULL)
+ errx(1, "failed to allocate fd_monitors");
+#endif /* __rtems__ */
for (i = 0; i < NUM_PRIORITIES; i++)
TAILQ_INIT(&fd_monitor_tree[i]);
@@ -307,7 +344,12 @@ session(void)
/* schedular can change select() mask, so we reset
* the working copy here */
+#ifndef __rtems__
active_mask = preset_mask;
+#else /* __rtems__ */
+ memcpy(allocated_active_mask, allocated_preset_mask,
+ allocated_mask_size);
+#endif /* __rtems__ */
error = select(nfds + 1, &active_mask, NULL, NULL, timeout);
if (error < 0) {
@@ -356,6 +398,11 @@ close_session()
flushsainfo();
close_sockets();
backupsa_clean();
+#ifdef __rtems__
+ free(allocated_preset_mask); allocated_preset_mask = NULL;
+ free(allocated_active_mask); allocated_active_mask = NULL;
+ free(allocated_fd_monitors); allocated_fd_monitors = NULL;
+#endif /* __rtems__ */
plog(LLV_INFO, LOCATION, NULL, "racoon process %d shutdown\n", getpid());
diff --git a/libbsd.py b/libbsd.py
index 2f40662a..83450b59 100644
--- a/libbsd.py
+++ b/libbsd.py
@@ -135,6 +135,7 @@ _defaults = {
('freebsd/sys/dev/mii', '**/*.h', 'dev/mii'),
('freebsd/sys/dev/pci', '**/*.h', 'dev/pci'),
('freebsd/sys/dev/nvme', '**/*.h', 'dev/nvme'),
+ ('freebsd/sys/@CPU@/include', '**/*.h', ''),
('linux/include', '**/*.h', ''),
('mDNSResponder/mDNSCore', 'mDNSDebug.h', ''),
('mDNSResponder/mDNSCore', 'mDNSEmbeddedAPI.h', ''),
@@ -186,6 +187,7 @@ class rtems(builder.Module):
'rtems/rtems-bsd-set-if-input.c',
'rtems/rtems-bsd-shell-arp.c',
'rtems/rtems-bsd-shell-ifconfig.c',
+ 'rtems/rtems-bsd-shell-ifmcstat.c',
'rtems/rtems-bsd-shell-netstat.c',
'rtems/rtems-bsd-shell-nvmecontrol.c',
'rtems/rtems-bsd-shell-pfctl.c',
@@ -530,6 +532,11 @@ class base(builder.Module):
],
mm.generator['source']()
)
+ self.addPlainTextFile(
+ [
+ 'COPYRIGHT'
+ ]
+ )
#
# FDT
@@ -779,6 +786,7 @@ class dev_usb(builder.Module):
'sys/dev/usb/usb_ioctl.h',
'sys/dev/usb/usb_mbuf.h',
'sys/dev/usb/usb_msctest.h',
+ 'sys/dev/usb/usb_pci.h',
'sys/dev/usb/usb_pf.h',
'sys/dev/usb/usb_process.h',
'sys/dev/usb/usb_request.h',
@@ -841,6 +849,7 @@ class dev_usb_controller(builder.Module):
[
'sys/dev/usb/controller/ohci.c',
'sys/dev/usb/controller/ehci.c',
+ 'sys/dev/usb/controller/ehci_pci.c',
'sys/dev/usb/controller/usb_controller.c',
'sys/dev/usb/controller/dwc_otg.c',
'sys/dev/usb/controller/dwc_otg_fdt.c',
@@ -1435,7 +1444,6 @@ class dev_nic(builder.Module):
[
'sys/arm/include/cpufunc.h',
'sys/i386/include/md_var.h',
- 'sys/i386/include/intr_machdep.h',
'sys/i386/include/cpufunc.h',
'sys/x86/include/intr_machdep.h',
'sys/x86/include/specialreg.h',
@@ -1563,6 +1571,11 @@ class dev_nic_e1000(builder.Module):
],
mm.generator['source']()
)
+ self.addPlainTextFile(
+ [
+ 'sys/dev/e1000/LICENSE'
+ ]
+ )
#
# DEC Tulip aka Intel 21143
@@ -2429,6 +2442,11 @@ class opencrypto(builder.Module):
],
mm.generator['source']()
)
+ self.addPlainTextFile(
+ [
+ 'sys/contrib/libsodium/LICENSE'
+ ]
+ )
#
# Crypto
@@ -2621,7 +2639,7 @@ class pci(builder.Module):
]
)
self.addCPUDependentFreeBSDSourceFiles(
- [ 'i386' ],
+ [ 'i386', 'powerpc' ],
[
'sys/x86/x86/legacy.c',
'sys/x86/pci/pci_bus.c',
@@ -3026,9 +3044,16 @@ class user_space(builder.Module):
'usr.bin/netstat/unix.c',
'usr.bin/vmstat/vmstat.c',
'usr.sbin/arp/arp.c',
+ 'usr.sbin/ifmcstat/ifmcstat.c',
+ 'usr.sbin/ifmcstat/printb.c',
],
mm.generator['source'](['-DINET'])
)
+ self.addPlainTextFile(
+ [
+ 'contrib/libxo/LICENSE'
+ ]
+ )
#
# User space: wlanstats utility
@@ -4028,6 +4053,11 @@ class crypto_openssl(builder.Module):
mm.generator['from-FreeBSD-to-RTEMS-UserSpaceSourceConverter'](),
mm.generator['from-RTEMS-To-FreeBSD-SourceConverter'](),
mm.generator['buildSystemFragmentComposer']()))
+ self.addPlainTextFile(
+ [
+ 'crypto/openssl/LICENSE'
+ ]
+ )
#
# /usr/bin/openssl
@@ -4161,6 +4191,11 @@ class contrib_expat(builder.Module):
],
mm.generator['source'](cflags)
)
+ self.addPlainTextFile(
+ [
+ 'contrib/expat/COPYING'
+ ]
+ )
#
# Contrib libpcap
@@ -4262,6 +4297,11 @@ class contrib_libpcap(builder.Module):
],
mm.generator['source'](cflags)
)
+ self.addPlainTextFile(
+ [
+ 'contrib/libpcap/LICENSE'
+ ]
+ )
#
# /usr/sbin/tcpdump
@@ -4502,6 +4542,11 @@ class usr_sbin_tcpdump(builder.Module):
['freebsd/contrib/tcpdump',
'freebsd/usr.sbin/tcpdump/tcpdump'])
)
+ self.addPlainTextFile(
+ [
+ 'contrib/tcpdump/LICENSE'
+ ]
+ )
#
# /usr/sbin/wpa_supplicant
@@ -4816,6 +4861,11 @@ class usr_sbin_wpa_supplicant(builder.Module):
],
mm.generator['source']()
)
+ self.addPlainTextFile(
+ [
+ 'contrib/wpa/COPYING'
+ ]
+ )
#
# in_chksum Module
@@ -5139,6 +5189,7 @@ class tests(builder.Module):
self.addTest(mm.generator['test']('media01', ['test_main'],
runTest = False,
extraLibs = ['ftpd', 'telnetd']))
+ self.addTest(mm.generator['test']('mcast01', ['test_main']))
self.addTest(mm.generator['test']('vlan01', ['test_main'], netTest = True))
self.addTest(mm.generator['test']('lagg01', ['test_main'], netTest = True))
self.addTest(mm.generator['test']('log01', ['test_main']))
@@ -5179,6 +5230,7 @@ class tests(builder.Module):
self.addTest(mm.generator['test']('ipsec01', ['test_main']))
self.addTest(mm.generator['test']('openssl01', ['test_main']))
self.addTest(mm.generator['test']('openssl02', ['test_main']))
+ self.addTest(mm.generator['test']('tcpdump01', ['test_main']))
def load(mm):
diff --git a/rtemsbsd/include/bsp/nexus-devices.h b/rtemsbsd/include/bsp/nexus-devices.h
index d2ceab8e..86305e9c 100644
--- a/rtemsbsd/include/bsp/nexus-devices.h
+++ b/rtemsbsd/include/bsp/nexus-devices.h
@@ -197,6 +197,12 @@ SYSINIT_DRIVER_REFERENCE(ukphy, miibus);
RTEMS_BSD_DEFINE_NEXUS_DEVICE(fec, 0, 0, NULL);
SYSINIT_DRIVER_REFERENCE(ukphy, miibus);
-#endif
+#elif defined(LIBBSP_POWERPC_MOTOROLA_POWERPC_BSP_H)
+
+RTEMS_BSD_DRIVER_PC_LEGACY;
+RTEMS_BSD_DRIVER_PCI_DC;
+RTEMS_BSD_DRIVER_UKPHY;
+
+#endif /* LIBBSP_POWERPC_MOTOROLA_POWERPC_BSP_H */
#endif
diff --git a/rtemsbsd/include/machine/bus.h b/rtemsbsd/include/machine/bus.h
index 2f0e7ad6..a0c3d63a 100644
--- a/rtemsbsd/include/machine/bus.h
+++ b/rtemsbsd/include/machine/bus.h
@@ -6,9 +6,13 @@
* @brief TODO.
*
* File origin from FreeBSD 'sys/amd64/include/bus.h'.
+ *
+ * Conditionally supports PCI IO regions (IO Ports).
*/
/*-
+ * Copyright (c) 2021 Chris Johns. All rights reserved.
+ *
* Copyright (c) 2009, 2015 embedded brains GmbH. All rights reserved.
*
* embedded brains GmbH
@@ -25,7 +29,7 @@
* 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 as
* the first lines of this file unmodified.
@@ -34,7 +38,7 @@
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
- *
+ *
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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.
@@ -123,9 +127,46 @@
#endif
#ifdef __i386__
- #error "your include paths are wrong"
+ #error "x86 has its own bus.h; check your include paths are correct"
#endif
+#include <bsp.h>
+
+/*
+ * BSP PCI Support
+ *
+ * The RTEMS Nexus bus support can optionaly support PC PCI spaces that
+ * mapped to BSP speciic address spaces. Add the following define to
+ * the BSP header file to enable this support:
+ *
+ * #define BSP_HAS_PC_PCI
+ *
+ * If enabled a BSP must support the following IO region calls:
+ *
+ * inb : read 8 bits
+ * outb : write 8 bits
+ * inw : read 16 bits
+ * outw : write 16 bits
+ * inl : read 32 bits
+ * outl : write 32 bits
+ *
+ * The BSP needs to provide the DRAM address space offset
+ * PCI_DRAM_OFFSET. This is the base address of the DRAM as seen by a
+ * PCI master.
+ *
+ * i386 BSPs have a special bus.h file and do not use this file.
+ */
+
+#ifdef BSP_HAS_PC_PCI
+
+/*
+ * Values for the bus space tag, not to be used directly by MI code.
+ */
+#define BSP_BUS_SPACE_IO 0 /* space is i/o space */
+#define BSP_BUS_SPACE_MEM 1 /* space is mem space */
+
+#endif /* BSP_HAS_PC_PCI */
+
/*
* Bus address alignment.
*/
@@ -144,6 +185,7 @@
/*
* Bus access.
*/
+#define BUS_SPACE_INVALID_DATA (~0U)
#define BUS_SPACE_UNRESTRICTED (~0U)
/*
@@ -223,36 +265,152 @@ bus_space_barrier(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size
}
/*
+ * BSP Bus Space Map Support
+ *
+ * A BSP can provide the following as C macros in the BSP header
+ * (bsp.h) to speicalise for special BSP specific bus operations:
+ *
+ * RTEMS_BSP_READ_1
+ * RTEMS_BSP_READ_2
+ * RTEMS_BSP_READ_4
+ * RTEMS_BSP_READ_8
+ * RTEMS_BSP_WRITE_1
+ * RTEMS_BSP_WRITE_2
+ * RTEMS_BSP_WRITE_4
+ * RTEMS_BSP_WRITE_8
+ */
+
+static __inline uint8_t
+bsp_bus_space_read_1(const uint8_t __volatile *bsp)
+{
+#if defined(RTEMS_BSP_READ_1)
+ return RTEMS_BSP_READ_1(bsp);
+#else
+ return (*bsp);
+#endif
+}
+
+static __inline uint16_t
+bsp_bus_space_read_2(const uint16_t __volatile *bsp)
+{
+#if defined(RTEMS_BSP_READ_2)
+ return RTEMS_BSP_READ_2(bsp);
+#else
+ return (*bsp);
+#endif
+}
+
+static __inline uint32_t
+bsp_bus_space_read_4(const uint32_t __volatile *bsp)
+{
+#if defined(RTEMS_BSP_READ_4)
+ return RTEMS_BSP_READ_4(bsp);
+#else
+ return (*bsp);
+#endif
+}
+
+static __inline uint64_t
+bsp_bus_space_read_8(const uint64_t __volatile *bsp)
+{
+#if defined(RTEMS_BSP_READ_8)
+ return RTEMS_BSP_READ_8(bsp);
+#else
+ return (*bsp);
+#endif
+}
+
+static __inline void
+bsp_bus_space_write_1(uint8_t __volatile *bsp, uint8_t val)
+{
+#if defined(RTEMS_BSP_WRITE_1)
+ RTEMS_BSP_WRITE_1(bsp, val);
+#else
+ *bsp = val;
+#endif
+}
+
+static __inline void
+bsp_bus_space_write_2(uint16_t __volatile *bsp, uint16_t val)
+{
+#if defined(RTEMS_BSP_WRITE_2)
+ RTEMS_BSP_WRITE_2(bsp, val);
+#else
+ *bsp = val;
+#endif
+}
+
+static __inline void
+bsp_bus_space_write_4(uint32_t __volatile *bsp, uint32_t val)
+{
+#if defined(RTEMS_BSP_WRITE_4)
+ RTEMS_BSP_WRITE_4(bsp, val);
+#else
+ *bsp = val;
+#endif
+}
+
+static __inline void
+bsp_bus_space_write_8(uint64_t __volatile *bsp, uint64_t val)
+{
+#if defined(RTEMS_BSP_WRITE_8)
+ RTEMS_BSP_WRITE_8(bsp, val);
+#else
+ *bsp = val;
+#endif
+}
+
+
+/*
* Read 1 unit of data from bus space described by the tag, handle and ofs
* tuple. A unit of data can be 1 byte, 2 bytes, 4 bytes or 8 bytes. The
* data is returned.
*/
static __inline uint8_t
-bus_space_read_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs)
+bus_space_read_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ return inb(bsh + ofs);
+ }
+#endif
uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
- return (*bsp);
+ return bsp_bus_space_read_1(bsp);
}
static __inline uint16_t
-bus_space_read_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs)
+bus_space_read_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ return inw(bsh + ofs);
+ }
+#endif
uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
- return (*bsp);
+ return bsp_bus_space_read_2(bsp);
}
static __inline uint32_t
-bus_space_read_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs)
+bus_space_read_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ return inl(bsh + ofs);
+ }
+#endif
uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
- return (*bsp);
+ return bsp_bus_space_read_4(bsp);
}
static __inline uint64_t
-bus_space_read_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs)
+bus_space_read_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO)
+ return BUS_SPACE_INVALID_DATA;
+#endif
uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
- return (*bsp);
+ return bsp_bus_space_read_8(bsp);
}
@@ -262,35 +420,58 @@ bus_space_read_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_
* data is passed by value.
*/
static __inline void
-bus_space_write_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs,
+bus_space_write_1(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
uint8_t val)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ outb(val, bsh + ofs);
+ return;
+ }
+#endif
uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
- *bsp = val;
+ bsp_bus_space_write_1(bsp, val);
}
static __inline void
-bus_space_write_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs,
+bus_space_write_2(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
uint16_t val)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ outw(val, bsh + ofs);
+ return;
+ }
+#endif
uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
- *bsp = val;
+ bsp_bus_space_write_2(bsp, val);
}
static __inline void
-bus_space_write_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs,
+bus_space_write_4(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
uint32_t val)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ outl(val, bsh + ofs);
+ return;
+ }
+#endif
uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
- *bsp = val;
+ bsp_bus_space_write_4(bsp, val);
}
static __inline void
-bus_space_write_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh, bus_size_t ofs,
+bus_space_write_8(bus_space_tag_t bst, bus_space_handle_t bsh, bus_size_t ofs,
uint64_t val)
{
+#ifdef BSP_HAS_PC_PCI
+ if (bst == BSP_BUS_SPACE_IO) {
+ return;
+ }
+#endif
uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
- *bsp = val;
+ bsp_bus_space_write_8(bsp, val);
}
@@ -305,7 +486,7 @@ bus_space_read_multi_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bufp++ = *bsp;
+ *bufp++ = bsp_bus_space_read_1(bsp);
}
}
@@ -315,7 +496,7 @@ bus_space_read_multi_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bufp++ = *bsp;
+ *bufp++ = bsp_bus_space_read_2(bsp);
}
}
@@ -325,7 +506,7 @@ bus_space_read_multi_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bufp++ = *bsp;
+ *bufp++ = bsp_bus_space_read_4(bsp);
}
}
@@ -335,7 +516,7 @@ bus_space_read_multi_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bufp++ = *bsp;
+ *bufp++ = bsp_bus_space_read_8(bsp);
}
}
@@ -351,7 +532,7 @@ bus_space_write_multi_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = *bufp++;
+ bsp_bus_space_write_1(bsp, *bufp++);
}
}
@@ -361,7 +542,7 @@ bus_space_write_multi_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = *bufp++;
+ bsp_bus_space_write_2(bsp, *bufp++);
}
}
@@ -371,7 +552,7 @@ bus_space_write_multi_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = *bufp++;
+ bsp_bus_space_write_4(bsp, *bufp++);
}
}
@@ -381,7 +562,7 @@ bus_space_write_multi_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = *bufp++;
+ bsp_bus_space_write_8(bsp, *bufp++);
}
}
@@ -396,10 +577,9 @@ static __inline void
bus_space_read_region_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint8_t *bufp, bus_size_t count)
{
+ uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
- *bufp++ = *bsp;
- ofs += 1;
+ *bufp++ = bsp_bus_space_read_1(bsp++);
}
}
@@ -407,10 +587,9 @@ static __inline void
bus_space_read_region_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint16_t *bufp, bus_size_t count)
{
+ uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
- *bufp++ = *bsp;
- ofs += 2;
+ *bufp++ = bsp_bus_space_read_2(bsp++);
}
}
@@ -418,10 +597,9 @@ static __inline void
bus_space_read_region_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint32_t *bufp, bus_size_t count)
{
+ uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
- *bufp++ = *bsp;
- ofs += 4;
+ *bufp++ = bsp_bus_space_read_4(bsp++);
}
}
@@ -429,10 +607,9 @@ static __inline void
bus_space_read_region_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint64_t *bufp, bus_size_t count)
{
+ uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
- *bufp++ = *bsp;
- ofs += 8;
+ *bufp++ = bsp_bus_space_read_8(bsp++);
}
}
@@ -447,10 +624,9 @@ static __inline void
bus_space_write_region_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, const uint8_t *bufp, bus_size_t count)
{
+ uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
- *bsp = *bufp++;
- ofs += 1;
+ bsp_bus_space_write_1(bsp++, *bufp++);
}
}
@@ -458,10 +634,9 @@ static __inline void
bus_space_write_region_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, const uint16_t *bufp, bus_size_t count)
{
+ uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
- *bsp = *bufp++;
- ofs += 2;
+ bsp_bus_space_write_2(bsp++, *bufp++);
}
}
@@ -469,10 +644,9 @@ static __inline void
bus_space_write_region_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, const uint32_t *bufp, bus_size_t count)
{
+ uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
- *bsp = *bufp++;
- ofs += 4;
+ bsp_bus_space_write_4(bsp++, *bufp++);
}
}
@@ -480,10 +654,9 @@ static __inline void
bus_space_write_region_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, const uint64_t *bufp, bus_size_t count)
{
+ uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
- *bsp = *bufp++;
- ofs += 8;
+ bsp_bus_space_write_8(bsp++, *bufp++);
}
}
@@ -499,7 +672,7 @@ bus_space_set_multi_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = val;
+ bsp_bus_space_write_1(bsp, val);
}
}
@@ -509,7 +682,7 @@ bus_space_set_multi_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = val;
+ bsp_bus_space_write_2(bsp, val);
}
}
@@ -519,7 +692,7 @@ bus_space_set_multi_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = val;
+ bsp_bus_space_write_4(bsp, val);
}
}
@@ -529,7 +702,7 @@ bus_space_set_multi_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
{
uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- *bsp = val;
+ bsp_bus_space_write_8(bsp, val);
}
}
@@ -544,10 +717,9 @@ static __inline void
bus_space_set_region_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint8_t val, bus_size_t count)
{
+ uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint8_t __volatile *bsp = (uint8_t __volatile *)(bsh + ofs);
- *bsp = val;
- ofs += 1;
+ bsp_bus_space_write_1(bsp++, val);
}
}
@@ -555,10 +727,9 @@ static __inline void
bus_space_set_region_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint16_t val, bus_size_t count)
{
+ uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint16_t __volatile *bsp = (uint16_t __volatile *)(bsh + ofs);
- *bsp = val;
- ofs += 2;
+ bsp_bus_space_write_2(bsp++, val);
}
}
@@ -566,10 +737,9 @@ static __inline void
bus_space_set_region_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint32_t val, bus_size_t count)
{
+ uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint32_t __volatile *bsp = (uint32_t __volatile *)(bsh + ofs);
- *bsp = val;
- ofs += 4;
+ bsp_bus_space_write_4(bsp++, val);
}
}
@@ -577,10 +747,9 @@ static __inline void
bus_space_set_region_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh,
bus_size_t ofs, uint64_t val, bus_size_t count)
{
+ uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
while (count-- > 0) {
- uint64_t __volatile *bsp = (uint64_t __volatile *)(bsh + ofs);
- *bsp = val;
- ofs += 8;
+ bsp_bus_space_write_8(bsp++, val);
}
}
@@ -596,23 +765,21 @@ static __inline void
bus_space_copy_region_1(bus_space_tag_t bst __unused, bus_space_handle_t bsh1,
bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, bus_size_t count)
{
- bus_addr_t dst = bsh1 + ofs1;
- bus_addr_t src = bsh2 + ofs2;
- uint8_t __volatile *dstp = (uint8_t __volatile *) dst;
- uint8_t __volatile *srcp = (uint8_t __volatile *) src;
+ uint8_t __volatile *dst = (uint8_t __volatile *)(bsh1 + ofs1);
+ uint8_t __volatile *src = (uint8_t __volatile *)(bsh2 + ofs2);
if (dst > src) {
src += count - 1;
dst += count - 1;
while (count-- > 0) {
- *dstp = *srcp;
- src -= 1;
- dst -= 1;
+ bsp_bus_space_write_1(dst, bsp_bus_space_read_1(src));
+ src--;
+ dst--;
}
} else {
while (count-- > 0) {
- *dstp = *srcp;
- src += 1;
- dst += 1;
+ bsp_bus_space_write_1(dst, bsp_bus_space_read_1(src));
+ src++;
+ dst++;
}
}
}
@@ -621,23 +788,21 @@ static __inline void
bus_space_copy_region_2(bus_space_tag_t bst __unused, bus_space_handle_t bsh1,
bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, bus_size_t count)
{
- bus_addr_t dst = bsh1 + ofs1;
- bus_addr_t src = bsh2 + ofs2;
- uint16_t __volatile *dstp = (uint16_t __volatile *) dst;
- uint16_t __volatile *srcp = (uint16_t __volatile *) src;
+ uint16_t __volatile *dst = (uint16_t __volatile *)(bsh1 + ofs1);
+ uint16_t __volatile *src = (uint16_t __volatile *)(bsh2 + ofs2);;
if (dst > src) {
- src += (count - 1) << 1;
- dst += (count - 1) << 1;
+ src += count - 1;
+ dst += count - 1;
while (count-- > 0) {
- *dstp = *srcp;
- src -= 2;
- dst -= 2;
+ bsp_bus_space_write_2(dst, bsp_bus_space_read_2(src));
+ src--;
+ dst--;
}
} else {
while (count-- > 0) {
- *dstp = *srcp;
- src += 2;
- dst += 2;
+ bsp_bus_space_write_2(dst, bsp_bus_space_read_2(src));
+ src++;
+ dst++;
}
}
}
@@ -646,23 +811,21 @@ static __inline void
bus_space_copy_region_4(bus_space_tag_t bst __unused, bus_space_handle_t bsh1,
bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, bus_size_t count)
{
- bus_addr_t dst = bsh1 + ofs1;
- bus_addr_t src = bsh2 + ofs2;
- uint32_t __volatile *dstp = (uint32_t __volatile *) dst;
- uint32_t __volatile *srcp = (uint32_t __volatile *) src;
+ uint32_t __volatile *dst = (uint32_t __volatile *)(bsh1 + ofs1);
+ uint32_t __volatile *src = (uint32_t __volatile *)(bsh2 + ofs2);;
if (dst > src) {
- src += (count - 1) << 2;
- dst += (count - 1) << 2;
+ src += count - 1;
+ dst += count - 1;
while (count-- > 0) {
- *dstp = *srcp;
- src -= 4;
- dst -= 4;
+ bsp_bus_space_write_4(dst, bsp_bus_space_read_4(src));
+ src--;
+ dst--;
}
} else {
while (count-- > 0) {
- *dstp = *srcp;
- src += 4;
- dst += 4;
+ bsp_bus_space_write_4(dst, bsp_bus_space_read_4(src));
+ src++;
+ dst++;
}
}
}
@@ -671,23 +834,21 @@ static __inline void
bus_space_copy_region_8(bus_space_tag_t bst __unused, bus_space_handle_t bsh1,
bus_size_t ofs1, bus_space_handle_t bsh2, bus_size_t ofs2, bus_size_t count)
{
- bus_addr_t dst = bsh1 + ofs1;
- bus_addr_t src = bsh2 + ofs2;
- uint64_t __volatile *dstp = (uint64_t __volatile *) dst;
- uint64_t __volatile *srcp = (uint64_t __volatile *) src;
+ uint64_t __volatile *dst = (uint64_t __volatile *)(bsh1 + ofs1);
+ uint64_t __volatile *src = (uint64_t __volatile *)(bsh2 + ofs2);;
if (dst > src) {
- src += (count - 1) << 3;
- dst += (count - 1) << 3;
+ src += count - 1;
+ dst += count - 1;
while (count-- > 0) {
- *dstp = *srcp;
- src -= 8;
- dst -= 8;
+ bsp_bus_space_write_8(dst, bsp_bus_space_read_8(src));
+ src--;
+ dst--;
}
} else {
while (count-- > 0) {
- *dstp = *srcp;
- src += 8;
- dst += 8;
+ bsp_bus_space_write_8(dst, bsp_bus_space_read_8(src));
+ src++;
+ dst++;
}
}
}
diff --git a/rtemsbsd/include/machine/rtems-bsd-commands.h b/rtemsbsd/include/machine/rtems-bsd-commands.h
index 036734ee..d314471f 100644
--- a/rtemsbsd/include/machine/rtems-bsd-commands.h
+++ b/rtemsbsd/include/machine/rtems-bsd-commands.h
@@ -50,6 +50,8 @@ int rtems_bsd_command_arp(int argc, char **argv);
int rtems_bsd_command_ifconfig(int argc, char **argv);
+int rtems_bsd_command_ifmcstat(int argc, char **argv);
+
int rtems_bsd_command_netstat(int argc, char **argv);
int rtems_bsd_command_nvmecontrol(int argc, char **argv);
diff --git a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
index ff545dc0..c2d71eed 100644
--- a/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
+++ b/rtemsbsd/include/machine/rtems-bsd-nexus-bus.h
@@ -77,6 +77,7 @@
* RTEMS_BSD_DRIVER_ICSPHY
* RTEMS_BSD_DRIVER_REPHY
* RTEMS_BSD_DRIVER_PHY_MIC
+ * RTEMS_BSD_DRIVER_UKPHY
*/
#if !defined(RTEMS_BSD_NEXUS_BUS_h)
@@ -441,6 +442,14 @@ extern "C" {
SYSINIT_DRIVER_REFERENCE(re, pci);
#endif /* RTEMS_BSD_DRIVER_PCI_RE */
+/*
+ * DEC Tulip Driver
+ */
+#if !defined(RTEMS_BSD_DRIVER_PCI_DC)
+ #define RTEMS_BSD_DRIVER_PCI_DC \
+ SYSINIT_DRIVER_REFERENCE(dc, pci);
+#endif /* RTEMS_BSD_DRIVER_PCI_DC */
+
/**
** MMI Physical Layer Support.
**/
@@ -477,6 +486,14 @@ extern "C" {
SYSINIT_DRIVER_REFERENCE(micphy, miibus);
#endif /* RTEMS_BSD_DRIVER_PHY_MIC */
+/*
+ * UK PHY (for unknown PHY devices)
+ */
+#if !defined(RTEMS_BSD_DRIVER_UKPHY)
+ #define RTEMS_BSD_DRIVER_UKPHY \
+ SYSINIT_DRIVER_REFERENCE(ukphy, miibus);
+#endif /* RTEMS_BSD_DRIVER_UKPHY */
+
#ifdef __cplusplus
}
#endif /* __cplusplus */
diff --git a/rtemsbsd/include/machine/rtems-bsd-program.h b/rtemsbsd/include/machine/rtems-bsd-program.h
index f71ac9cd..96d4bfef 100644
--- a/rtemsbsd/include/machine/rtems-bsd-program.h
+++ b/rtemsbsd/include/machine/rtems-bsd-program.h
@@ -60,6 +60,12 @@ rtems_bsd_program_call_main_with_data_restore(const char *name,
int (*main)(int, char **), int argc, char **argv,
void *data_buf, const size_t data_size);
+void *
+rtems_bsd_program_add_destructor(void (*destructor)(void *), void *arg);
+
+void
+rtems_bsd_program_remove_destructor(void *cookie, bool call);
+
void
rtems_bsd_program_exit(int exit_code) __dead2;
diff --git a/rtemsbsd/include/rtems/netcmds-config.h b/rtemsbsd/include/rtems/netcmds-config.h
index bba2d307..bc493af4 100644
--- a/rtemsbsd/include/rtems/netcmds-config.h
+++ b/rtemsbsd/include/rtems/netcmds-config.h
@@ -30,7 +30,11 @@ extern rtems_shell_cmd_t rtems_shell_PING_Command;
extern rtems_shell_cmd_t rtems_shell_PING6_Command;
extern rtems_shell_cmd_t rtems_shell_IFCONFIG_Command;
+
+extern rtems_shell_cmd_t rtems_shell_IFMCSTAT_Command;
+
extern rtems_shell_cmd_t rtems_shell_ROUTE_Command;
+
extern rtems_shell_cmd_t rtems_shell_NETSTAT_Command;
extern rtems_shell_cmd_t rtems_shell_DHCPCD_Command;
diff --git a/rtemsbsd/nfsclient/nfs.c b/rtemsbsd/nfsclient/nfs.c
index d6f43305..3b8a5925 100644
--- a/rtemsbsd/nfsclient/nfs.c
+++ b/rtemsbsd/nfsclient/nfs.c
@@ -397,71 +397,36 @@ DirInfo dip;
/* Macro for accessing serporid fields
*/
-#define SERP_ARGS(node) ((node)->serporid.serporid_u.serporid.arg_u)
-#define SERP_ATTR(node) ((node)->serporid.serporid_u.serporid.attributes)
-#define SERP_FILE(node) ((node)->serporid.serporid_u.serporid.file)
-
-/*
- * FIXME: The use of the serporid structure with several embedded unions to
- * split up the specific NFS request/response structures is quite a hack. It
- * breaks on 64-bit targets due to the presence of pointer members which affect
- * the overall alignment. Use a packed serporidok structure to hopefully fix
- * this issue.
- */
+#define SERP_ARGS(node) ((node)->serporid.serporid)
+#define SERP_ATTR(node) ((node)->serporid.serporid.attributes)
+#define SERP_FILE(node) ((node)->serporid.serporid.file)
typedef struct serporidok {
fattr attributes;
- nfs_fh file;
union {
- struct {
- filename name;
- } diroparg;
- struct {
- sattr attributes;
- } sattrarg;
- struct {
- uint32_t offset;
- uint32_t count;
- uint32_t totalcount;
- } readarg;
- struct {
- uint32_t beginoffset;
- uint32_t offset;
- uint32_t totalcount;
- struct {
- uint32_t data_len;
- char* data_val;
- } data;
- } writearg;
- struct {
- filename name;
- sattr attributes;
- } createarg;
- struct {
- filename name;
- diropargs to;
- } renamearg;
- struct {
- diropargs to;
- } linkarg;
- struct {
- filename name;
- nfspath to;
- sattr attributes;
- } symlinkarg;
- struct {
- nfscookie cookie;
- uint32_t count;
- } readdirarg;
- } arg_u;
-} RTEMS_PACKED serporidok;
+ nfs_fh file;
+ diropargs diroparg;
+ sattrargs sattrarg;
+ readargs readarg;
+ writeargs writearg;
+ createargs createarg;
+ renameargs renamearg;
+ linkargs linkarg;
+ symlinkargs symlinkarg;
+ readdirargs readdirarg;
+ };
+} serporidok;
+/*
+ * The nfsstat is an enum, so has an integer alignment. The serporid contains
+ * pointers, so has at least a pointer alignment. The packed attribute ensures
+ * that there is no gap between the status and serporid members on 64-bit
+ * targets.
+ */
typedef struct serporid {
nfsstat status;
- union {
- serporidok serporid;
- } serporid_u;
-} serporid;
+ serporidok serporid;
+} RTEMS_PACKED serporid;
/* an XDR routine to encode/decode the inverted diropres
* into an nfsnodestat;
@@ -493,7 +458,7 @@ xdr_serporid(XDR *xdrs, serporid *objp)
return FALSE;
switch (objp->status) {
case NFS_OK:
- if (!xdr_serporidok(xdrs, &objp->serporid_u.serporid))
+ if (!xdr_serporidok(xdrs, &objp->serporid))
return FALSE;
break;
default:
@@ -2040,7 +2005,7 @@ char *dupname;
rtems_clock_get_tod_timeval(&now);
- SERP_ARGS(node).createarg.name = dupname;
+ SERP_ARGS(node).createarg.where.name = dupname;
SERP_ARGS(node).createarg.attributes.mode = mode;
SERP_ARGS(node).createarg.attributes.uid = nfs->uid;
SERP_ARGS(node).createarg.attributes.gid = nfs->gid;
@@ -2134,7 +2099,7 @@ char *dupname;
rtems_clock_get_tod_timeval(&now);
- SERP_ARGS(node).symlinkarg.name = dupname;
+ SERP_ARGS(node).symlinkarg.from.name = dupname;
SERP_ARGS(node).symlinkarg.to = (nfspath) target;
SERP_ARGS(node).symlinkarg.attributes.mode = S_IFLNK | S_IRWXU | S_IRWXG | S_IRWXO;
@@ -2231,7 +2196,7 @@ static int nfs_rename(
nfs_fh *toDirDst = &SERP_ARGS(oldParentNode).renamearg.to.dir;
nfsstat status;
- SERP_ARGS(oldParentNode).renamearg.name = oldNode->str;
+ SERP_ARGS(oldParentNode).renamearg.from.name = oldNode->str;
SERP_ARGS(oldParentNode).renamearg.to.name = dupname;
memcpy(toDirDst, toDirSrc, sizeof(*toDirDst));
diff --git a/rtemsbsd/powerpc/include/machine/legacyvar.h b/rtemsbsd/powerpc/include/machine/legacyvar.h
new file mode 100644
index 00000000..8683a0e5
--- /dev/null
+++ b/rtemsbsd/powerpc/include/machine/legacyvar.h
@@ -0,0 +1,2 @@
+/* See freebsd/sys/x86/include/machine/legacyvar.h */
+#include <x86/include/machine/legacyvar.h>
diff --git a/rtemsbsd/powerpc/include/machine/pci_cfgreg.h b/rtemsbsd/powerpc/include/machine/pci_cfgreg.h
new file mode 100644
index 00000000..1bfa468e
--- /dev/null
+++ b/rtemsbsd/powerpc/include/machine/pci_cfgreg.h
@@ -0,0 +1,2 @@
+/* See freebsd/sys/x86/include/machine/pci_cfgreg.h */
+#include <x86/include/machine/pci_cfgreg.h>
diff --git a/rtemsbsd/rtems/program-internal.h b/rtemsbsd/rtems/program-internal.h
index da817130..2104c064 100644
--- a/rtemsbsd/rtems/program-internal.h
+++ b/rtemsbsd/rtems/program-internal.h
@@ -60,6 +60,12 @@ struct program_allocmem_item {
LIST_ENTRY(program_allocmem_item) entries;
};
+struct program_destructor {
+ void (*destructor)(void *);
+ void *arg;
+ LIST_ENTRY(program_destructor) link;
+};
+
struct rtems_bsd_program_control {
void *context;
int exit_code;
@@ -68,6 +74,7 @@ struct rtems_bsd_program_control {
LIST_HEAD(, program_fd_item) open_fd;
LIST_HEAD(, program_file_item) open_file;
LIST_HEAD(, program_allocmem_item) allocated_mem;
+ LIST_HEAD(, program_destructor) destructors;
};
struct rtems_bsd_program_control *rtems_bsd_program_get_control_or_null(void);
diff --git a/rtemsbsd/rtems/rtems-bsd-shell-ifmcstat.c b/rtemsbsd/rtems/rtems-bsd-shell-ifmcstat.c
new file mode 100644
index 00000000..c8fbd4a1
--- /dev/null
+++ b/rtemsbsd/rtems/rtems-bsd-shell-ifmcstat.c
@@ -0,0 +1,36 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/*
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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 <rtems/netcmds-config.h>
+#include <machine/rtems-bsd-commands.h>
+
+rtems_shell_cmd_t rtems_shell_IFMCSTAT_Command = {
+ .name = "ifmcstat",
+ .usage = "ifmcstat [args]",
+ .topic = "net",
+ .command = rtems_bsd_command_ifmcstat
+};
diff --git a/rtemsbsd/rtems/rtems-kernel-bus-dma.c b/rtemsbsd/rtems/rtems-kernel-bus-dma.c
index 8c15e92b..d148e434 100644
--- a/rtemsbsd/rtems/rtems-kernel-bus-dma.c
+++ b/rtemsbsd/rtems/rtems-kernel-bus-dma.c
@@ -247,7 +247,6 @@ bus_dmamem_alloc(bus_dma_tag_t dmat, void** vaddr, int flags,
if (*vaddr == NULL) {
free(*mapp, M_DEVBUF);
-
return ENOMEM;
}
@@ -288,6 +287,10 @@ bus_dmamap_load_buffer(bus_dma_tag_t dmat, bus_dma_segment_t segs[],
vm_offset_t vaddr = (vm_offset_t)buf;
int seg;
+#ifdef RTEMS_BSP_PCI_MEM_REGION_BASE
+ vaddr += RTEMS_BSP_PCI_MEM_REGION_BASE;
+#endif
+
lastaddr = *lastaddrp;
bmask = ~(dmat->boundary - 1);
diff --git a/rtemsbsd/rtems/rtems-kernel-nexus.c b/rtemsbsd/rtems/rtems-kernel-nexus.c
index bf840a17..8fc879fe 100644
--- a/rtemsbsd/rtems/rtems-kernel-nexus.c
+++ b/rtemsbsd/rtems/rtems-kernel-nexus.c
@@ -59,9 +59,35 @@
#include <rtems/bsd/bsd.h>
#include <rtems/irq-extension.h>
+#include <bsp.h>
+
+/*
+ * BSP PCI Support
+ *
+ * The RTEMS Nexus bus support can optionaly support PCI spaces that
+ * map to BSP speciic address spaces. The BSP needs to provide the
+ * following:
+ *
+ * RTEMS_BSP_PCI_IO_REGION_BASE
+ * The base address of the IO port region of the address space
+ *
+ * RTEMS_BSP_PCI_MEM_REGION_BASE
+ * The base address of the memory region of the address space
+ *
+ * i386 (x86) BSPs have a special bus.h file and do not use these settings.
+ */
+
/* #define DISABLE_INTERRUPT_EXTENSION */
-#if defined(__i386__) || defined(FDT)
+#if defined(__i386__)
+#define RTEMS_BSP_PCI_IO_REGION_BASE 0
+#endif
+
+#if !defined(RTEMS_BSP_PCI_MEM_REGION_BASE)
+#define RTEMS_BSP_PCI_MEM_REGION_BASE 0
+#endif
+
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE) || defined(FDT)
#define ENABLE_RESOURCE_ACTIVATE_DEACTIVATE
#endif
@@ -77,7 +103,7 @@ static struct rman mem_rman;
static struct rman irq_rman;
-#ifdef __i386__
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE)
static struct rman port_rman;
#endif
@@ -111,9 +137,9 @@ nexus_probe(device_t dev)
err = rman_manage_region(&irq_rman, irq_rman.rm_start, irq_rman.rm_end);
BSD_ASSERT(err == 0);
-#ifdef __i386__
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE)
port_rman.rm_start = 0;
- port_rman.rm_end = 0xffff;
+ port_rman.rm_end = ~0UL;
port_rman.rm_type = RMAN_ARRAY;
port_rman.rm_descr = "I/O ports";
err = rman_init(&port_rman) != 0;
@@ -156,6 +182,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
struct resource *res = NULL;
struct rman *rm;
const rtems_bsd_device *nd;
+ rman_res_t base = RTEMS_BSP_PCI_MEM_REGION_BASE;
switch (type) {
case SYS_RES_MEMORY:
@@ -164,9 +191,10 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
case SYS_RES_IRQ:
rm = &irq_rman;
break;
-#ifdef __i386__
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE)
case SYS_RES_IOPORT:
rm = &port_rman;
+ base = RTEMS_BSP_PCI_IO_REGION_BASE;
break;
#endif
default:
@@ -185,7 +213,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
if (res != NULL) {
rman_set_rid(res, *rid);
rman_set_bushandle(res,
- rman_get_start(res));
+ rman_get_start(res) + base);
}
};
@@ -193,7 +221,7 @@ nexus_alloc_resource(device_t bus, device_t child, int type, int *rid,
}
}
-#ifdef __i386__
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE)
/*
* FIXME: This is a quick and dirty hack. Simply reserve resources of
* this kind. See also pci_reserve_map().
@@ -225,16 +253,22 @@ nexus_activate_resource(device_t bus, device_t child, int type, int rid,
{
switch (type) {
-#ifdef __i386__
+#if defined(RTEMS_BSP_PCI_IO_REGION_BASE)
case SYS_RES_IOPORT:
+#ifdef __i386__
rman_set_bustag(res, X86_BUS_SPACE_IO);
+#else
+ rman_set_bushandle(res,
+ rman_get_start(res) + RTEMS_BSP_PCI_IO_REGION_BASE);
+#endif
break;
#endif
case SYS_RES_MEMORY:
#ifdef __i386__
rman_set_bustag(res, X86_BUS_SPACE_MEM);
#else
- rman_set_bushandle(res, rman_get_start(res));
+ rman_set_bushandle(res,
+ rman_get_start(res) + RTEMS_BSP_PCI_MEM_REGION_BASE);
#endif
break;
}
diff --git a/rtemsbsd/rtems/rtems-program.c b/rtemsbsd/rtems/rtems-program.c
index 204ed248..1ca8e3b9 100644
--- a/rtemsbsd/rtems/rtems-program.c
+++ b/rtemsbsd/rtems/rtems-program.c
@@ -224,6 +224,18 @@ allocmem_free_all(struct rtems_bsd_program_control *prog_ctrl)
}
}
+static void
+call_destructors(struct rtems_bsd_program_control *prog_ctrl)
+{
+ struct program_destructor *node;
+ struct program_destructor *tmp;
+
+ LIST_FOREACH_SAFE(node, &prog_ctrl->destructors, link, tmp) {
+ (*node->destructor)(node->arg);
+ free(node);
+ }
+}
+
int
rtems_bsd_program_call(const char *name, int (*prog)(void *), void *context)
{
@@ -251,6 +263,7 @@ rtems_bsd_program_call(const char *name, int (*prog)(void *), void *context)
LIST_INIT(&prog_ctrl->open_fd);
LIST_INIT(&prog_ctrl->open_file);
LIST_INIT(&prog_ctrl->allocated_mem);
+ LIST_INIT(&prog_ctrl->destructors);
if (setjmp(prog_ctrl->return_context) == 0) {
exit_code = (*prog)(context);
@@ -262,10 +275,48 @@ rtems_bsd_program_call(const char *name, int (*prog)(void *), void *context)
fd_close_all(prog_ctrl);
file_close_all(prog_ctrl);
allocmem_free_all(prog_ctrl);
+ call_destructors(prog_ctrl);
free(prog_ctrl);
return (exit_code);
}
+void *
+rtems_bsd_program_add_destructor(void (*destructor)(void *), void *arg)
+{
+ struct rtems_bsd_program_control *prog_ctrl;
+ struct program_destructor *node;
+
+ prog_ctrl = rtems_bsd_program_get_control_or_null();
+ if (prog_ctrl == NULL) {
+ return (NULL);
+ }
+
+ node = malloc(sizeof(*node));
+ if (node == NULL) {
+ return (NULL);
+ }
+
+ node->destructor = destructor;
+ node->arg = arg;
+ LIST_INSERT_HEAD(&prog_ctrl->destructors, node, link);
+ return (node);
+}
+
+void
+rtems_bsd_program_remove_destructor(void *cookie, bool call)
+{
+ struct program_destructor *node;
+
+ node = cookie;
+ LIST_REMOVE(node, link);
+
+ if (call) {
+ (*node->destructor)(node->arg);
+ }
+
+ free(node);
+}
+
void
rtems_bsd_program_exit(int exit_code)
{
diff --git a/rtemsbsd/sys/dev/atsam/if_atsam.c b/rtemsbsd/sys/dev/atsam/if_atsam.c
index ff8219f4..21a28fcd 100644
--- a/rtemsbsd/sys/dev/atsam/if_atsam.c
+++ b/rtemsbsd/sys/dev/atsam/if_atsam.c
@@ -42,6 +42,7 @@
#include <sys/types.h>
#include <sys/param.h>
#include <sys/mbuf.h>
+#include <sys/sbuf.h>
#include <sys/socket.h>
#include <sys/sockio.h>
#include <sys/kernel.h>
@@ -49,7 +50,9 @@
#include <sys/bus.h>
#include <sys/sysctl.h>
+#include <net/bpf.h>
#include <net/if.h>
+#include <net/if_dl.h>
#include <net/if_var.h>
#include <net/if_types.h>
#include <net/if_media.h>
@@ -66,6 +69,7 @@
#include <rtems/bsd/local/miibus_if.h>
#include <rtems/bsd/if_atsam.h>
+#include <rtems/bsd/bsd.h>
/*
* Number of interfaces supported by the driver
@@ -90,46 +94,40 @@
/** The runtime pin configure list for GMAC */
#define BOARD_GMAC_RUN_PINS BOARD_GMAC_PINS
-/** Multicast Enable */
-#define GMAC_MC_ENABLE (1u << 6)
-#define HASH_INDEX_AMOUNT 6
-#define HASH_ELEMENTS_PER_INDEX 8
-#define MAC_ADDR_MASK 0x0000FFFFFFFFFFFF
-#define MAC_IDX_MASK (1u << 0)
-
-/** Promiscuous Mode Enable */
-#define GMAC_PROM_ENABLE (1u << 4)
-
/** RX Defines */
#define GMAC_RX_BUFFER_SIZE 1536
#define GMAC_RX_BUF_DESC_ADDR_MASK 0xFFFFFFFC
-#define GMAC_RX_SET_OFFSET (1u << 15)
-#define GMAC_RX_SET_USED_WRAP ((1u << 1) | (1u << 0))
-#define GMAC_RX_SET_WRAP (1u << 1)
-#define GMAC_RX_SET_USED (1u << 0)
-/** TX Defines */
-#define GMAC_TX_SET_EOF (1u << 15)
-#define GMAC_TX_SET_WRAP (1u << 30)
-#define GMAC_TX_SET_USED (1u << 31)
#define GMAC_DESCRIPTOR_ALIGNMENT 8
/** Events */
#define ATSAMV7_ETH_RX_EVENT_INTERRUPT RTEMS_EVENT_1
-#define ATSAMV7_ETH_TX_EVENT_INTERRUPT RTEMS_EVENT_2
-#define ATSAMV7_ETH_START_TRANSMIT_EVENT RTEMS_EVENT_3
-
-#define ATSAMV7_ETH_RX_DATA_OFFSET 2
-
-#define WATCHDOG_TIMEOUT 5
/* FIXME: Make these configurable */
#define MDIO_RETRIES 10
#define MDIO_PHY MII_PHY_ANY
-#define RXBUF_COUNT 8
-#define TXBUF_COUNT 64
#define IGNORE_RX_ERR false
+#define RX_INTERRUPTS (GMAC_ISR_RCOMP | GMAC_ISR_RXUBR | GMAC_ISR_ROVR)
+
+#define RX_DESC_LOG2 3
+#define RX_DESC_COUNT (1U << RX_DESC_LOG2)
+#define RX_DESC_WRAP(idx) \
+ ((((idx) + 1) & RX_DESC_COUNT) >> (RX_DESC_LOG2 - 1))
+RTEMS_STATIC_ASSERT(RX_DESC_WRAP(RX_DESC_COUNT - 1) ==
+ GMAC_RX_WRAP_BIT, rx_desc_wrap);
+RTEMS_STATIC_ASSERT(RX_DESC_WRAP(RX_DESC_COUNT - 2) ==
+ 0, rx_desc_no_wrap);
+
+#define TX_DESC_LOG2 6
+#define TX_DESC_COUNT (1U << TX_DESC_LOG2)
+#define TX_DESC_WRAP(idx) \
+ ((((idx) + 1) & TX_DESC_COUNT) << (30 - TX_DESC_LOG2))
+RTEMS_STATIC_ASSERT(TX_DESC_WRAP(TX_DESC_COUNT - 1) ==
+ GMAC_TX_WRAP_BIT, tx_desc_wrap);
+RTEMS_STATIC_ASSERT(TX_DESC_WRAP(TX_DESC_COUNT - 2) ==
+ 0, tx_desc_no_wrap);
+
/** The PINs for GMAC */
static const Pin gmacPins[] = { BOARD_GMAC_RUN_PINS };
@@ -139,11 +137,13 @@ typedef struct if_atsam_gmac {
uint32_t retries;
} if_atsam_gmac;
-typedef struct ring_buffer {
- unsigned tx_bd_used;
- unsigned tx_bd_free;
- size_t length;
-} ring_buffer;
+struct if_atsam_tx_bds {
+ volatile sGmacTxDescriptor bds[TX_DESC_COUNT];
+};
+
+struct if_atsam_rx_bds {
+ volatile sGmacRxDescriptor bds[RX_DESC_COUNT];
+};
/*
* Per-device data
@@ -156,17 +156,16 @@ typedef struct if_atsam_softc {
struct ifnet *ifp;
struct mtx mtx;
if_atsam_gmac Gmac_inst;
+ size_t tx_idx_head;
+ size_t tx_idx_tail;
+ struct if_atsam_tx_bds *tx;
+ struct mbuf *tx_mbufs[TX_DESC_COUNT];
+ size_t rx_idx_head;
+ struct if_atsam_rx_bds *rx;
+ struct mbuf *rx_mbufs[RX_DESC_COUNT];
uint8_t GMacAddress[6];
rtems_id rx_daemon_tid;
- rtems_id tx_daemon_tid;
rtems_vector_number interrupt_number;
- struct mbuf **rx_mbuf;
- struct mbuf **tx_mbuf;
- volatile sGmacTxDescriptor *tx_bd_base;
- size_t rx_bd_fill_idx;
- size_t amount_rx_buf;
- size_t amount_tx_buf;
- ring_buffer tx_ring;
struct callout tick_ch;
/*
@@ -190,13 +189,12 @@ typedef struct if_atsam_softc {
struct if_atsam_stats {
/* Software */
uint32_t rx_overrun_errors;
+ uint32_t rx_used_bit_reads;
uint32_t rx_interrupts;
- uint32_t tx_complete_int;
uint32_t tx_tur_errors;
uint32_t tx_rlex_errors;
uint32_t tx_tfc_errors;
uint32_t tx_hresp_errors;
- uint32_t tx_interrupts;
/* Hardware */
uint64_t octets_transm;
@@ -243,6 +241,8 @@ typedef struct if_atsam_softc {
uint32_t tcp_checksum_errors;
uint32_t udp_checksum_errors;
} stats;
+
+ int if_flags;
} if_atsam_softc;
static void if_atsam_poll_hw_stats(struct if_atsam_softc *sc);
@@ -251,27 +251,6 @@ static void if_atsam_poll_hw_stats(struct if_atsam_softc *sc);
#define IF_ATSAM_UNLOCK(sc) mtx_unlock(&(sc)->mtx)
-static void if_atsam_event_send(rtems_id task, rtems_event_set event)
-{
- rtems_event_send(task, event);
-}
-
-
-static void if_atsam_event_receive(if_atsam_softc *sc, rtems_event_set in)
-{
- rtems_event_set out;
-
- IF_ATSAM_UNLOCK(sc);
- rtems_event_receive(
- in,
- RTEMS_EVENT_ANY | RTEMS_WAIT,
- RTEMS_NO_TIMEOUT,
- &out
- );
- IF_ATSAM_LOCK(sc);
-}
-
-
static struct mbuf *if_atsam_new_mbuf(struct ifnet *ifp)
{
struct mbuf *m;
@@ -356,11 +335,10 @@ if_atsam_miibus_readreg(device_t dev, int phy, int reg)
static int
if_atsam_miibus_writereg(device_t dev, int phy, int reg, int data)
{
- uint8_t err;
if_atsam_softc *sc = device_get_softc(dev);
IF_ATSAM_LOCK(sc);
- err = if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw,
+ (void)if_atsam_write_phy(sc->Gmac_inst.gGmacd.pHw,
(uint8_t)phy, (uint8_t)reg, data, sc->Gmac_inst.retries);
IF_ATSAM_UNLOCK(sc);
@@ -403,63 +381,53 @@ if_atsam_init_phy(if_atsam_gmac *gmac_inst, uint32_t mck,
static void if_atsam_interrupt_handler(void *arg)
{
if_atsam_softc *sc = (if_atsam_softc *)arg;
- uint32_t irq_status_val;
- rtems_event_set rx_event = 0;
- rtems_event_set tx_event = 0;
Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ uint32_t is;
/* Get interrupt status */
- irq_status_val = GMAC_GetItStatus(pHw, 0);
+ is = pHw->GMAC_ISR;
- /* Check receive interrupts */
- if ((irq_status_val & GMAC_IER_ROVR) != 0) {
- ++sc->stats.rx_overrun_errors;
- rx_event = ATSAMV7_ETH_RX_EVENT_INTERRUPT;
- }
- if ((irq_status_val & GMAC_IER_RCOMP) != 0) {
- rx_event = ATSAMV7_ETH_RX_EVENT_INTERRUPT;
+ if (__predict_false((is & GMAC_TX_ERR_BIT) != 0)) {
+ if ((is & GMAC_IER_TUR) != 0) {
+ ++sc->stats.tx_tur_errors;
+ }
+ if ((is & GMAC_IER_RLEX) != 0) {
+ ++sc->stats.tx_rlex_errors;
+ }
+ if ((is & GMAC_IER_TFC) != 0) {
+ ++sc->stats.tx_tfc_errors;
+ }
+ if ((is & GMAC_IER_HRESP) != 0) {
+ ++sc->stats.tx_hresp_errors;
+ }
}
- /* Send events to receive task and switch off rx interrupts */
- if (rx_event != 0) {
+
+ /* Check receive interrupts */
+ if (__predict_true((is & RX_INTERRUPTS) != 0)) {
+ if (__predict_false((is & GMAC_ISR_RXUBR) != 0)) {
+ ++sc->stats.rx_used_bit_reads;
+ }
+
+ if (__predict_false((is & GMAC_ISR_ROVR) != 0)) {
+ ++sc->stats.rx_overrun_errors;
+ }
+
++sc->stats.rx_interrupts;
- /* Erase the interrupts for RX completion and errors */
- GMAC_DisableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
- (void)if_atsam_event_send(sc->rx_daemon_tid, rx_event);
- }
- if ((irq_status_val & GMAC_IER_TUR) != 0) {
- ++sc->stats.tx_tur_errors;
- tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT;
- }
- if ((irq_status_val & GMAC_IER_RLEX) != 0) {
- ++sc->stats.tx_rlex_errors;
- tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT;
- }
- if ((irq_status_val & GMAC_IER_TFC) != 0) {
- ++sc->stats.tx_tfc_errors;
- tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT;
- }
- if ((irq_status_val & GMAC_IER_HRESP) != 0) {
- ++sc->stats.tx_hresp_errors;
- tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT;
- }
- if ((irq_status_val & GMAC_IER_TCOMP) != 0) {
- ++sc->stats.tx_complete_int;
- tx_event = ATSAMV7_ETH_TX_EVENT_INTERRUPT;
- }
- /* Send events to transmit task and switch off tx interrupts */
- if (tx_event != 0) {
- ++sc->stats.tx_interrupts;
- /* Erase the interrupts for TX completion and errors */
- GMAC_DisableIt(pHw, GMAC_INT_TX_BITS, 0);
- (void)if_atsam_event_send(sc->tx_daemon_tid, tx_event);
+
+ /* Disable RX interrupts */
+ pHw->GMAC_IDR = RX_INTERRUPTS;
+
+ (void)rtems_event_send(sc->rx_daemon_tid,
+ ATSAMV7_ETH_RX_EVENT_INTERRUPT);
}
}
-static void rx_update_mbuf(struct mbuf *m, sGmacRxDescriptor *buffer_desc)
+static void
+if_atsam_rx_update_mbuf(struct mbuf *m, uint32_t status)
{
int frame_len;
- frame_len = (int) (buffer_desc->status.bm.len);
+ frame_len = (int)(status & GMAC_LENGTH_FRAME);
m->m_data = mtod(m, char*)+ETHER_ALIGN;
m->m_len = frame_len;
@@ -467,7 +435,7 @@ static void rx_update_mbuf(struct mbuf *m, sGmacRxDescriptor *buffer_desc)
/* check checksum offload result */
m->m_pkthdr.csum_flags = 0;
- switch (buffer_desc->status.bm.typeIDMatchOrCksumResult) {
+ switch ((status >> 22) & 0x3) {
case GMAC_RXDESC_ST_CKSUM_RESULT_IP_CHECKED:
m->m_pkthdr.csum_flags = CSUM_IP_CHECKED | CSUM_IP_VALID;
m->m_pkthdr.csum_data = 0xffff;
@@ -481,21 +449,17 @@ static void rx_update_mbuf(struct mbuf *m, sGmacRxDescriptor *buffer_desc)
}
}
-/*
- * Receive daemon
- */
-static void if_atsam_rx_daemon(void *arg)
+static void
+if_atsam_rx_daemon(rtems_task_argument arg)
{
if_atsam_softc *sc = (if_atsam_softc *)arg;
struct ifnet *ifp = sc->ifp;
- rtems_event_set events = 0;
- void *rx_bd_base;
- struct mbuf *m;
- struct mbuf *n;
- volatile sGmacRxDescriptor *buffer_desc;
- uint32_t tmp_rx_bd_address;
- size_t i;
+ volatile sGmacRxDescriptor *base;
+ struct if_atsam_rx_bds *rx;
Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ size_t idx;
+ struct mbuf **mbufs;
+ struct mbuf *m;
IF_ATSAM_LOCK(sc);
@@ -506,47 +470,37 @@ static void if_atsam_rx_daemon(void *arg)
}
/* Allocate memory space for priority queue descriptor list */
- rx_bd_base = rtems_cache_coherent_allocate(sizeof(sGmacRxDescriptor),
+ base = rtems_cache_coherent_allocate(sizeof(*base),
GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(rx_bd_base != NULL);
+ assert(base != NULL);
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
- buffer_desc->addr.val = GMAC_RX_SET_USED_WRAP;
- buffer_desc->status.val = 0;
+ base->addr.val = GMAC_RX_OWNERSHIP_BIT | GMAC_RX_WRAP_BIT;
+ base->status.val = 0;
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 1);
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 2);
+ GMAC_SetRxQueue(pHw, (uint32_t)base, 1);
+ GMAC_SetRxQueue(pHw, (uint32_t)base, 2);
/* Allocate memory space for buffer descriptor list */
- rx_bd_base = rtems_cache_coherent_allocate(
- sc->amount_rx_buf * sizeof(sGmacRxDescriptor),
+ rx = rtems_cache_coherent_allocate(sizeof(*rx),
GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(rx_bd_base != NULL);
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
+ assert(rx != NULL);
+ sc->rx = rx;
+ mbufs = &sc->rx_mbufs[0];
/* Create descriptor list and mark as empty */
- for (sc->rx_bd_fill_idx = 0; sc->rx_bd_fill_idx < sc->amount_rx_buf;
- ++sc->rx_bd_fill_idx) {
+ for (idx = 0; idx < RX_DESC_COUNT; ++idx) {
m = if_atsam_new_mbuf(ifp);
assert(m != NULL);
- sc->rx_mbuf[sc->rx_bd_fill_idx] = m;
- buffer_desc->addr.val = ((uint32_t)m->m_data) &
- GMAC_RX_BUF_DESC_ADDR_MASK;
- buffer_desc->status.val = 0;
- if (sc->rx_bd_fill_idx == (sc->amount_rx_buf - 1)) {
- buffer_desc->addr.bm.bWrap = 1;
- } else {
- buffer_desc++;
- }
+ mbufs[idx] = m;
+ rx->bds[idx].addr.val = mtod(m, uint32_t) | RX_DESC_WRAP(idx);
}
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base;
/* Set 2 Byte Receive Buffer Offset */
- pHw->GMAC_NCFGR |= GMAC_RX_SET_OFFSET;
+ pHw->GMAC_NCFGR |= GMAC_NCFGR_RXBUFO(2);
/* Write Buffer Queue Base Address Register */
GMAC_ReceiveEnable(pHw, 0);
- GMAC_SetRxQueue(pHw, (uint32_t)buffer_desc, 0);
+ GMAC_SetRxQueue(pHw, (uint32_t)&rx->bds[0], 0);
/* Set address for address matching */
GMAC_SetAddress(pHw, 0, sc->GMacAddress);
@@ -554,306 +508,230 @@ static void if_atsam_rx_daemon(void *arg)
/* Enable Receiving of data */
GMAC_ReceiveEnable(pHw, 1);
- /* Setup the interrupts for RX completion and errors */
- GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
+ IF_ATSAM_UNLOCK(sc);
- sc->rx_bd_fill_idx = 0;
+ idx = 0;
while (true) {
- /* Wait for events */
- if_atsam_event_receive(sc, ATSAMV7_ETH_RX_EVENT_INTERRUPT);
+ rtems_event_set out;
- /*
- * Check for all packets with a set ownership bit
- */
- while (buffer_desc->addr.bm.bOwnership == 1) {
- if (buffer_desc->status.bm.bEof == 1) {
- m = sc->rx_mbuf[sc->rx_bd_fill_idx];
+ sc->rx_idx_head = idx;
- /* New mbuf for desc */
- n = if_atsam_new_mbuf(ifp);
- if (n != NULL) {
- rx_update_mbuf(m, buffer_desc);
+ /* Enable RX interrupts */
+ pHw->GMAC_IER = RX_INTERRUPTS;
- IF_ATSAM_UNLOCK(sc);
- sc->ifp->if_input(ifp, m);
- IF_ATSAM_LOCK(sc);
- m = n;
- } else {
- (void)if_atsam_event_send(
- sc->tx_daemon_tid, ATSAMV7_ETH_START_TRANSMIT_EVENT);
- }
- sc->rx_mbuf[sc->rx_bd_fill_idx] = m;
- tmp_rx_bd_address = (uint32_t)m->m_data &
- GMAC_RX_BUF_DESC_ADDR_MASK;
-
- /* Switch pointer to next buffer descriptor */
- if (sc->rx_bd_fill_idx ==
- (sc->amount_rx_buf - 1)) {
- tmp_rx_bd_address |= GMAC_RX_SET_WRAP;
- sc->rx_bd_fill_idx = 0;
- } else {
- ++sc->rx_bd_fill_idx;
- }
+ (void) rtems_event_receive(ATSAMV7_ETH_RX_EVENT_INTERRUPT,
+ RTEMS_EVENT_ALL | RTEMS_WAIT, RTEMS_NO_TIMEOUT, &out);
- /*
- * Give ownership to GMAC for further processing
- */
- tmp_rx_bd_address &= ~GMAC_RX_SET_USED;
- _ARM_Data_synchronization_barrier();
- buffer_desc->addr.val = tmp_rx_bd_address;
+ while (true) {
+ uint32_t addr;
+ uint32_t status;
- buffer_desc = (sGmacRxDescriptor *)rx_bd_base
- + sc->rx_bd_fill_idx;
+ addr = rx->bds[idx].addr.val;
+ if ((addr & GMAC_RX_OWNERSHIP_BIT) == 0) {
+ break;
}
- }
- /* Setup the interrupts for RX completion and errors */
- GMAC_EnableIt(pHw, GMAC_IER_RCOMP | GMAC_IER_ROVR, 0);
- }
-}
-/*
- * Update of current transmit buffer position.
- */
-static void if_atsam_tx_bd_pos_update(size_t *pos, size_t amount_tx_buf)
-{
- *pos = (*pos + 1) % amount_tx_buf;
-}
+ status = rx->bds[idx].status.val;
+ m = mbufs[idx];
-/*
- * Is RingBuffer empty
- */
-static bool if_atsam_ring_buffer_empty(ring_buffer *ring_buffer)
-{
- return (ring_buffer->tx_bd_used == ring_buffer->tx_bd_free);
-}
+ if (__predict_true((status & GMAC_RX_EOF_BIT) != 0)) {
+ struct mbuf *n;
-/*
- * Is RingBuffer full
- */
-static bool if_atsam_ring_buffer_full(ring_buffer *ring_buffer)
-{
- size_t tx_bd_used_next = ring_buffer->tx_bd_used;
+ n = if_atsam_new_mbuf(ifp);
+ if (n != NULL) {
+ if_atsam_rx_update_mbuf(m, status);
+ (*ifp->if_input)(ifp, m);
+ m = n;
+ }
+ } else {
+ if_inc_counter(ifp, IFCOUNTER_IERRORS, 1);
+ }
- if_atsam_tx_bd_pos_update(&tx_bd_used_next, ring_buffer->length);
- return (tx_bd_used_next == ring_buffer->tx_bd_free);
-}
+ mbufs[idx] = m;
+ rx->bds[idx].addr.val = mtod(m, uint32_t) |
+ RX_DESC_WRAP(idx);
-/*
- * Cleanup transmit file descriptors by freeing mbufs which are not needed any
- * longer due to correct transmission.
- */
-static void if_atsam_tx_bd_cleanup(if_atsam_softc *sc)
-{
- struct mbuf *m;
- volatile sGmacTxDescriptor *cur;
- bool eof_needed = false;
-
- while (!if_atsam_ring_buffer_empty(&sc->tx_ring)){
- cur = sc->tx_bd_base + sc->tx_ring.tx_bd_free;
- if (((cur->status.bm.bUsed == 1) && !eof_needed) || eof_needed) {
- eof_needed = true;
- cur->status.val |= GMAC_TX_SET_USED;
- m = sc->tx_mbuf[sc->tx_ring.tx_bd_free];
- m_free(m);
- sc->tx_mbuf[sc->tx_ring.tx_bd_free] = 0;
- if_atsam_tx_bd_pos_update(&sc->tx_ring.tx_bd_free,
- sc->tx_ring.length);
- if (cur->status.bm.bLastBuffer) {
- eof_needed = false;
- }
- } else {
- break;
+ idx = (idx + 1) % RX_DESC_COUNT;
}
}
}
-/*
- * Prepare Ethernet frame to start transmission.
- */
-static bool if_atsam_send_packet(if_atsam_softc *sc, struct mbuf *m)
+static void
+if_atsam_tx_reclaim(struct if_atsam_softc *sc, struct ifnet *ifp)
{
- volatile sGmacTxDescriptor *cur;
- volatile sGmacTxDescriptor *start_packet_tx_bd = 0;
- int pos = 0;
- uint32_t tmp_val = 0;
- Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
- bool success;
- int csum_flags = m->m_pkthdr.csum_flags;
+ uint32_t head_idx;
+ uint32_t tail_idx;
+ volatile sGmacTxDescriptor *base;
- if_atsam_tx_bd_cleanup(sc);
- /* Wait for interrupt in case no buffer descriptors are available */
- /* Wait for events */
- while (true) {
- if (if_atsam_ring_buffer_full(&sc->tx_ring)) {
- /* Setup the interrupts for TX completion and errors */
- GMAC_EnableIt(pHw, GMAC_INT_TX_BITS, 0);
- success = false;
+ head_idx = sc->tx_idx_head;
+ tail_idx = sc->tx_idx_tail;
+ base = &sc->tx->bds[0];
+
+ while (head_idx != tail_idx) {
+ uint32_t status;
+ ift_counter cnt;
+ struct mbuf *m;
+
+ status = base[tail_idx].status.val;
+
+ if ((status & GMAC_TX_USED_BIT) == 0) {
break;
}
- /*
- * Get current mbuf for data fill
- */
- cur = &sc->tx_bd_base[sc->tx_ring.tx_bd_used];
- /* Set the transfer data */
- if (m->m_len) {
- uintptr_t cache_adjustment = mtod(m, uintptr_t) % 32;
-
- rtems_cache_flush_multiple_data_lines(
- mtod(m, const char *) - cache_adjustment,
- (size_t)(m->m_len + cache_adjustment));
-
- cur->addr = mtod(m, uint32_t);
- tmp_val = (uint32_t)m->m_len | GMAC_TX_SET_USED;
- if (sc->tx_ring.tx_bd_used == (sc->tx_ring.length - 1)) {
- tmp_val |= GMAC_TX_SET_WRAP;
- }
- if (pos == 0) {
- start_packet_tx_bd = cur;
- }
- sc->tx_mbuf[sc->tx_ring.tx_bd_used] = m;
- m = m->m_next;
- if_atsam_tx_bd_pos_update(&sc->tx_ring.tx_bd_used,
- sc->tx_ring.length);
+ if (__predict_true((status & GMAC_TX_ERR_BITS) == 0)) {
+ cnt = IFCOUNTER_OPACKETS;
} else {
- /* Discard empty mbufs */
- m = m_free(m);
+ cnt = IFCOUNTER_OERRORS;
}
- /*
- * Send out the buffer once the complete mbuf_chain has been
- * processed
- */
- if (m == NULL) {
- tmp_val |= GMAC_TX_SET_EOF;
- tmp_val &= ~GMAC_TX_SET_USED;
- if ((csum_flags & (CSUM_IP | CSUM_TCP | CSUM_UDP |
- CSUM_TCP_IPV6 | CSUM_UDP_IPV6)) != 0) {
- start_packet_tx_bd->status.bm.bNoCRC = 0;
- } else {
- start_packet_tx_bd->status.bm.bNoCRC = 1;
- }
- _ARM_Data_synchronization_barrier();
- cur->status.val = tmp_val;
- start_packet_tx_bd->status.val &= ~GMAC_TX_SET_USED;
- _ARM_Data_synchronization_barrier();
- GMAC_TransmissionStart(pHw);
- success = true;
- break;
- } else {
- if (pos > 0) {
- tmp_val &= ~GMAC_TX_SET_USED;
+ while ((m = sc->tx_mbufs[tail_idx]) == NULL ) {
+ base[tail_idx].status.val = status | GMAC_TX_USED_BIT;
+ tail_idx = (tail_idx + 1) % TX_DESC_COUNT;
+ status = base[tail_idx].status.val;
+
+ if (__predict_false((status & GMAC_TX_ERR_BITS) != 0)) {
+ cnt = IFCOUNTER_OERRORS;
}
- pos++;
- cur->status.val = tmp_val;
}
+
+ base[tail_idx].status.val = status | GMAC_TX_USED_BIT;
+ if_inc_counter(ifp, cnt, 1);
+ sc->tx_mbufs[tail_idx] = NULL;
+ m_freem(m);
+
+ tail_idx = (tail_idx + 1) % TX_DESC_COUNT;
}
- return success;
-}
+ sc->tx_idx_tail = tail_idx;
+}
-/*
- * Transmit daemon
- */
-static void if_atsam_tx_daemon(void *arg)
+static void
+if_atsam_cache_flush(uintptr_t begin, uintptr_t size)
{
- if_atsam_softc *sc = (if_atsam_softc *)arg;
- rtems_event_set events = 0;
- sGmacTxDescriptor *buffer_desc;
- int bd_number;
- void *tx_bd_base;
- struct mbuf *m;
- bool success;
+ uintptr_t end;
+ uintptr_t mask;
+
+ /* Align begin and end of the data to a cache line */
+ end = begin + size;
+ mask = CPU_CACHE_LINE_BYTES - 1;
+ begin &= ~mask;
+ end = (end + mask) & ~mask;
+ rtems_cache_flush_multiple_data_lines((void *)begin, end - begin);
+}
- IF_ATSAM_LOCK(sc);
+static int
+if_atsam_tx_enqueue(struct if_atsam_softc *sc, struct ifnet *ifp, struct mbuf *m)
+{
+ size_t head_idx;
+ size_t tail_idx;
+ size_t capacity;
+ size_t idx;
+ volatile sGmacTxDescriptor *base;
+ volatile sGmacTxDescriptor *desc;
+ size_t bufs;
+ uint32_t status;
+ struct mbuf *n;
- Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
- struct ifnet *ifp = sc->ifp;
+ head_idx = sc->tx_idx_head;
+ tail_idx = sc->tx_idx_tail;
+ capacity = (tail_idx - head_idx - 1) % TX_DESC_COUNT;
- GMAC_TransmitEnable(pHw, 0);
+ idx = head_idx;
+ base = &sc->tx->bds[0];
+ bufs = 0;
+ n = m;
- /* Allocate memory space for priority queue descriptor list */
- tx_bd_base = rtems_cache_coherent_allocate(sizeof(sGmacTxDescriptor),
- GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(tx_bd_base != NULL);
+ do {
+ uint32_t size;
- buffer_desc = (sGmacTxDescriptor *)tx_bd_base;
- buffer_desc->addr = 0;
- buffer_desc->status.val = GMAC_TX_SET_USED | GMAC_TX_SET_WRAP;
+ desc = &base[idx];
- GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 1);
- GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 2);
+ size = (uint32_t)n->m_len;
+ if (__predict_true(size > 0)) {
+ uintptr_t begin;
- /* Allocate memory space for buffer descriptor list */
- tx_bd_base = rtems_cache_coherent_allocate(
- sc->amount_tx_buf * sizeof(sGmacTxDescriptor),
- GMAC_DESCRIPTOR_ALIGNMENT, 0);
- assert(tx_bd_base != NULL);
- buffer_desc = (sGmacTxDescriptor *)tx_bd_base;
+ ++bufs;
+ if (__predict_false(bufs > capacity)) {
+ return (ENOBUFS);
+ }
- /* Create descriptor list and mark as empty */
- for (bd_number = 0; bd_number < sc->amount_tx_buf; bd_number++) {
- buffer_desc->addr = 0;
- buffer_desc->status.val = GMAC_TX_SET_USED;
- if (bd_number == (sc->amount_tx_buf - 1)) {
- buffer_desc->status.bm.bWrap = 1;
- } else {
- buffer_desc++;
+ begin = mtod(n, uintptr_t);
+ desc->addr = (uint32_t)begin;
+ status = GMAC_TX_USED_BIT | TX_DESC_WRAP(idx) | size;
+ desc->status.val = status;
+ if_atsam_cache_flush(begin, size);
+ idx = (idx + 1) % TX_DESC_COUNT;
}
+
+ n = n->m_next;
+ } while (n != NULL);
+
+ sc->tx_idx_head = idx;
+
+ idx = (idx - 1) % TX_DESC_COUNT;
+ desc = &base[idx];
+ sc->tx_mbufs[idx] = m;
+ status = GMAC_TX_LAST_BUFFER_BIT;
+
+ while (idx != head_idx) {
+ desc->status.val = (desc->status.val & ~GMAC_TX_USED_BIT) |
+ status;
+ status = 0;
+
+ idx = (idx - 1) % TX_DESC_COUNT;
+ desc = &base[idx];
}
- buffer_desc = (sGmacTxDescriptor *)tx_bd_base;
- /* Write Buffer Queue Base Address Register */
- GMAC_SetTxQueue(pHw, (uint32_t)buffer_desc, 0);
+ desc->status.val = (desc->status.val & ~GMAC_TX_USED_BIT) | status;
+ _ARM_Data_synchronization_barrier();
+ sc->Gmac_inst.gGmacd.pHw->GMAC_NCR |= GMAC_NCR_TSTART;
+ ETHER_BPF_MTAP(ifp, m);
+ return (0);
+}
- /* Enable Transmission of data */
- GMAC_TransmitEnable(pHw, 1);
+static int
+if_atsam_transmit(struct ifnet *ifp, struct mbuf *m)
+{
+ struct if_atsam_softc *sc;
+ int error;
- /* Set variables in context */
- sc->tx_bd_base = tx_bd_base;
+ if (__predict_false((m->m_flags & M_VLANTAG) != 0)) {
+ struct mbuf *n;
- while (true) {
- /* Wait for events */
- if_atsam_event_receive(sc,
- ATSAMV7_ETH_START_TRANSMIT_EVENT |
- ATSAMV7_ETH_TX_EVENT_INTERRUPT);
- //printf("TX Transmit Event received\n");
-
- /*
- * Send packets till queue is empty
- */
- while (true) {
- /*
- * Get the mbuf chain to transmit
- */
- if_atsam_tx_bd_cleanup(sc);
- IF_DEQUEUE(&ifp->if_snd, m);
- if (!m) {
- ifp->if_drv_flags &= ~IFF_DRV_OACTIVE;
- break;
- }
- success = if_atsam_send_packet(sc, m);
- if (!success){
- break;
- }
+ n = ether_vlanencap(m, m->m_pkthdr.ether_vtag);
+ if (n == NULL) {
+ m_freem(m);
+ return (ENOBUFS);
}
+
+ m = n;
}
-}
+ sc = ifp->if_softc;
+ IF_ATSAM_LOCK(sc);
-/*
- * Send packet (caller provides header).
- */
-static void if_atsam_enet_start(struct ifnet *ifp)
-{
- if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
+ error = if_atsam_tx_enqueue(sc, ifp, m);
+ if_atsam_tx_reclaim(sc, ifp);
- ifp->if_drv_flags |= IFF_DRV_OACTIVE;
- if_atsam_event_send(sc->tx_daemon_tid,
- ATSAMV7_ETH_START_TRANSMIT_EVENT);
-}
+ if (__predict_false(error != 0)) {
+ struct mbuf *n;
+ n = m_defrag(m, M_NOWAIT);
+ if (n != NULL) {
+ m = n;
+ }
+
+ error = if_atsam_tx_enqueue(sc, ifp, m);
+ if (error != 0) {
+ m_freem(m);
+ if_inc_counter(ifp, IFCOUNTER_OQDROPS, 1);
+ }
+ }
+
+ IF_ATSAM_UNLOCK(sc);
+ return (error);
+}
static uint8_t if_atsam_get_gmac_linkspeed_from_media(uint32_t media_subtype)
{
@@ -975,23 +853,55 @@ if_atsam_tick(void *context)
callout_reset(&sc->tick_ch, hz, if_atsam_tick, sc);
}
+static void
+if_atsam_setup_tx(struct if_atsam_softc *sc)
+{
+ sGmacTxDescriptor *base;
+ struct if_atsam_tx_bds *tx;
+ size_t i;
+ Gmac *pHw;
-/*
- * Sets up the hardware and chooses the interface to be used
- */
-static void if_atsam_init(void *arg)
+ pHw = sc->Gmac_inst.gGmacd.pHw;
+ GMAC_TransmitEnable(pHw, 0);
+
+ /* Allocate memory space for priority queue descriptor list */
+ base = rtems_cache_coherent_allocate(sizeof(base),
+ GMAC_DESCRIPTOR_ALIGNMENT, 0);
+ assert(base != NULL);
+
+ base->addr = 0;
+ base->status.val = GMAC_TX_USED_BIT | GMAC_TX_WRAP_BIT;
+
+ GMAC_SetTxQueue(pHw, (uint32_t)base, 1);
+ GMAC_SetTxQueue(pHw, (uint32_t)base, 2);
+
+ /* Allocate memory space for buffer descriptor list */
+ tx = rtems_cache_coherent_allocate(sizeof(*sc->tx),
+ GMAC_DESCRIPTOR_ALIGNMENT, 0);
+ assert(tx != NULL);
+
+ /* Set variables in context */
+ sc->tx = tx;
+
+ /* Create descriptor list and mark as empty */
+ for (i = 0; i < TX_DESC_COUNT; ++i) {
+ tx->bds[i].addr = 0;
+ tx->bds[i].status.val = GMAC_TX_USED_BIT | TX_DESC_WRAP(i);
+ }
+
+ /* Write Buffer Queue Base Address Register */
+ GMAC_SetTxQueue(pHw, (uint32_t)&tx->bds[0], 0);
+
+ /* Enable Transmission of data */
+ GMAC_TransmitEnable(pHw, 1);
+}
+
+static void
+if_atsam_init(if_atsam_softc *sc)
{
rtems_status_code status;
-
- if_atsam_softc *sc = (if_atsam_softc *)arg;
- struct ifnet *ifp = sc->ifp;
uint32_t dmac_cfg = 0;
- uint32_t gmii_val = 0;
- if (ifp->if_flags & IFF_DRV_RUNNING) {
- return;
- }
- ifp->if_flags |= IFF_DRV_RUNNING;
sc->interrupt_number = GMAC_IRQn;
/* Enable Peripheral Clock */
@@ -1000,7 +910,6 @@ static void if_atsam_init(void *arg)
}
/* Setup interrupts */
NVIC_ClearPendingIRQ(GMAC_IRQn);
- NVIC_EnableIRQ(GMAC_IRQn);
/* Configuration of DMAC */
dmac_cfg = (GMAC_DCFGR_DRBS(GMAC_RX_BUFFER_SIZE >> 6)) |
@@ -1011,20 +920,17 @@ static void if_atsam_init(void *arg)
/* Enable hardware checksum offload for receive */
sc->Gmac_inst.gGmacd.pHw->GMAC_NCFGR |= GMAC_NCFGR_RXCOEN;
+ /* Use Multicast Hash Filter */
+ sc->Gmac_inst.gGmacd.pHw->GMAC_NCFGR |= GMAC_NCFGR_MTIHEN;
+ sc->Gmac_inst.gGmacd.pHw->GMAC_HRB = 0;
+ sc->Gmac_inst.gGmacd.pHw->GMAC_HRT = 0;
+
/* Shut down Transmit and Receive */
GMAC_ReceiveEnable(sc->Gmac_inst.gGmacd.pHw, 0);
GMAC_TransmitEnable(sc->Gmac_inst.gGmacd.pHw, 0);
GMAC_StatisticsWriteEnable(sc->Gmac_inst.gGmacd.pHw, 1);
- /*
- * Allocate mbuf pointers
- */
- sc->rx_mbuf = malloc(sc->amount_rx_buf * sizeof *sc->rx_mbuf,
- M_TEMP, M_NOWAIT);
- sc->tx_mbuf = malloc(sc->amount_tx_buf * sizeof *sc->tx_mbuf,
- M_TEMP, M_NOWAIT);
-
/* Install interrupt handler */
status = rtems_interrupt_handler_install(sc->interrupt_number,
"Ethernet",
@@ -1036,30 +942,143 @@ static void if_atsam_init(void *arg)
/*
* Start driver tasks
*/
- sc->rx_daemon_tid = rtems_bsdnet_newproc("SCrx", 4096,
- if_atsam_rx_daemon, sc);
- sc->tx_daemon_tid = rtems_bsdnet_newproc("SCtx", 4096,
- if_atsam_tx_daemon, sc);
+
+ status = rtems_task_create(rtems_build_name('S', 'C', 'r', 'x'),
+ rtems_bsd_get_task_priority(device_get_name(sc->dev)), 4096,
+ RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_MODES, &sc->rx_daemon_tid);
+ assert(status == RTEMS_SUCCESSFUL);
+
+ status = rtems_task_start(sc->rx_daemon_tid, if_atsam_rx_daemon,
+ (rtems_task_argument)sc);
+ assert(status == RTEMS_SUCCESSFUL);
callout_reset(&sc->tick_ch, hz, if_atsam_tick, sc);
+ if_atsam_setup_tx(sc);
+}
+
+static int
+if_atsam_get_hash_index(const uint8_t *eaddr)
+{
+ uint64_t eaddr64;
+ int index;
+ int i;
+
+ eaddr64 = eaddr[5];
+
+ for (i = 4; i >= 0; --i) {
+ eaddr64 <<= 8;
+ eaddr64 |= eaddr[i];
+ }
+
+ index = 0;
+
+ for (i = 0; i < 6; ++i) {
+ uint64_t bits;
+ int j;
+ int hash;
+
+ bits = eaddr64 >> i;
+ hash = bits & 1;
+
+ for (j = 1; j < 8; ++j) {
+ bits >>= 6;
+ hash ^= bits & 1;
+ }
+
+ index |= hash << i;
+ }
+
+ return index;
+}
+
+static void
+if_atsam_setup_rxfilter(struct if_atsam_softc *sc)
+{
+ struct ifnet *ifp;
+ struct ifmultiaddr *ifma;
+ uint64_t mhash;
+ Gmac *pHw;
+
+ pHw = sc->Gmac_inst.gGmacd.pHw;
+
+ if ((sc->ifp->if_flags & IFF_PROMISC) != 0) {
+ pHw->GMAC_NCFGR |= GMAC_NCFGR_CAF;
+ } else {
+ pHw->GMAC_NCFGR &= ~GMAC_NCFGR_CAF;
+ }
+
+ ifp = sc->ifp;
+
+ if ((ifp->if_flags & IFF_ALLMULTI))
+ mhash = 0xffffffffffffffffLLU;
+ else {
+ mhash = 0;
+ if_maddr_rlock(ifp);
+ CK_STAILQ_FOREACH(ifma, &sc->ifp->if_multiaddrs, ifma_link) {
+ if (ifma->ifma_addr->sa_family != AF_LINK)
+ continue;
+ mhash |= 1LLU << if_atsam_get_hash_index(
+ LLADDR((struct sockaddr_dl *) ifma->ifma_addr));
+ }
+ if_maddr_runlock(ifp);
+ }
+
+ pHw->GMAC_HRB = (uint32_t)mhash;
+ pHw->GMAC_HRT = (uint32_t)(mhash >> 32);
+}
+
+static void
+if_atsam_start_locked(struct if_atsam_softc *sc)
+{
+ struct ifnet *ifp = sc->ifp;
+ Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ return;
+ }
+
ifp->if_drv_flags |= IFF_DRV_RUNNING;
+
+ if_atsam_setup_rxfilter(sc);
+
+ /* Enable TX/RX */
+ pHw->GMAC_NCR |= GMAC_NCR_RXEN | GMAC_NCR_TXEN;
}
+static void
+if_atsam_start(void *arg)
+{
+ struct if_atsam_softc *sc = arg;
-/*
- * Stop the device
- */
-static void if_atsam_stop(struct if_atsam_softc *sc)
+ IF_ATSAM_LOCK(sc);
+ if_atsam_start_locked(sc);
+ IF_ATSAM_UNLOCK(sc);
+}
+
+static void
+if_atsam_stop_locked(struct if_atsam_softc *sc)
{
struct ifnet *ifp = sc->ifp;
Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ size_t i;
- ifp->if_flags &= ~IFF_DRV_RUNNING;
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
- /* Disable MDIO interface and TX/RX */
+ /* Disable TX/RX */
pHw->GMAC_NCR &= ~(GMAC_NCR_RXEN | GMAC_NCR_TXEN);
- pHw->GMAC_NCR &= ~GMAC_NCR_MPE;
+
+ /* Reinitialize the TX descriptors */
+
+ sc->tx_idx_head = 0;
+ sc->tx_idx_tail = 0;
+
+ for (i = 0; i < TX_DESC_COUNT; ++i) {
+ sc->tx->bds[i].addr = 0;
+ sc->tx->bds[i].status.val = GMAC_TX_USED_BIT | TX_DESC_WRAP(i);
+ m_freem(sc->tx_mbufs[i]);
+ sc->tx_mbufs[i] = NULL;
+ }
}
@@ -1070,7 +1089,7 @@ if_atsam_poll_hw_stats(struct if_atsam_softc *sc)
Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
octets = pHw->GMAC_OTLO;
- octets |= pHw->GMAC_OTHI << 32;
+ octets |= (uint64_t)pHw->GMAC_OTHI << 32;
sc->stats.octets_transm += octets;
sc->stats.frames_transm += pHw->GMAC_FT;
sc->stats.broadcast_frames_transm += pHw->GMAC_BCFT;
@@ -1092,7 +1111,7 @@ if_atsam_poll_hw_stats(struct if_atsam_softc *sc)
sc->stats.carrier_sense_errors += pHw->GMAC_CSE;
octets = pHw->GMAC_ORLO;
- octets |= pHw->GMAC_ORHI << 32;
+ octets |= (uint64_t)pHw->GMAC_ORHI << 32;
sc->stats.octets_rec += octets;
sc->stats.frames_rec += pHw->GMAC_FR;
sc->stats.broadcast_frames_rec += pHw->GMAC_BCFR;
@@ -1120,24 +1139,159 @@ if_atsam_poll_hw_stats(struct if_atsam_softc *sc)
sc->stats.udp_checksum_errors += pHw->GMAC_UCE;
}
+static int
+if_atsam_stats_reset(SYSCTL_HANDLER_ARGS)
+{
+ struct if_atsam_softc *sc = arg1;
+ int value;
+ int error;
+
+ value = 0;
+ error = sysctl_handle_int(oidp, &value, 0, req);
+ if (error != 0 || req->newptr == NULL) {
+ return (error);
+ }
+
+ if (value != 0) {
+ IF_ATSAM_LOCK(sc);
+ if_atsam_poll_hw_stats(sc);
+ memset(&sc->stats, 0, sizeof(sc->stats));
+ IF_ATSAM_UNLOCK(sc);
+ }
+
+ return (0);
+}
+
+static int
+if_atsam_sysctl_reg(SYSCTL_HANDLER_ARGS)
+{
+ u_int value;
+
+ value = *(uint32_t *)arg1;
+ return (sysctl_handle_int(oidp, &value, 0, req));
+}
+
+static int
+if_atsam_sysctl_tx_desc(SYSCTL_HANDLER_ARGS)
+{
+ struct if_atsam_softc *sc = arg1;
+ Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ struct sbuf *sb;
+ int error;
+ size_t i;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0) {
+ return (error);
+ }
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 1024, req);
+ if (sb == NULL) {
+ return (ENOMEM);
+ }
+
+ sbuf_printf(sb, "\n\tHead %u\n", sc->tx_idx_head);
+ sbuf_printf(sb, "\tTail %u\n", sc->tx_idx_tail);
+ sbuf_printf(sb, "\tDMA %u\n",
+ (pHw->GMAC_TBQB - (uintptr_t)&sc->tx->bds[0]) / 8);
+
+ for (i = 0; i < TX_DESC_COUNT; ++i) {
+ sbuf_printf(sb, "\t[%2u] %08x %08x\n", i,
+ sc->tx->bds[i].status.val, sc->tx->bds[i].addr);
+ }
+
+ error = sbuf_finish(sb);
+ sbuf_delete(sb);
+ return (error);
+}
+
+static int
+if_atsam_sysctl_rx_desc(SYSCTL_HANDLER_ARGS)
+{
+ struct if_atsam_softc *sc = arg1;
+ Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
+ struct sbuf *sb;
+ int error;
+ size_t i;
+
+ error = sysctl_wire_old_buffer(req, 0);
+ if (error != 0) {
+ return (error);
+ }
+
+ sb = sbuf_new_for_sysctl(NULL, NULL, 1024, req);
+ if (sb == NULL) {
+ return (ENOMEM);
+ }
+
+ sbuf_printf(sb, "\n\tHead %u\n", sc->rx_idx_head);
+ sbuf_printf(sb, "\tDMA %u\n",
+ (pHw->GMAC_RBQB - (uintptr_t)&sc->rx->bds[0]) / 8);
+
+ for (i = 0; i < RX_DESC_COUNT; ++i) {
+ sbuf_printf(sb, "\t[%2u] %08x %08x\n", i,
+ sc->rx->bds[i].status.val, sc->rx->bds[i].addr);
+ }
+
+ error = sbuf_finish(sb);
+ sbuf_delete(sb);
+ return (error);
+}
static void
if_atsam_add_sysctls(device_t dev)
{
struct if_atsam_softc *sc = device_get_softc(dev);
+ Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
struct sysctl_ctx_list *ctx;
+ struct sysctl_oid_list *base;
struct sysctl_oid_list *statsnode;
struct sysctl_oid_list *hwstatsnode;
struct sysctl_oid_list *child;
struct sysctl_oid *tree;
ctx = device_get_sysctl_ctx(dev);
- child = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
+ base = SYSCTL_CHILDREN(device_get_sysctl_tree(dev));
- tree = SYSCTL_ADD_NODE(ctx, child, OID_AUTO, "stats", CTLFLAG_RD,
+ tree = SYSCTL_ADD_NODE(ctx, base, OID_AUTO, "regs", CTLFLAG_RD,
+ NULL, "if_atsam registers");
+ child = SYSCTL_CHILDREN(tree);
+
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "txdesc", CTLTYPE_STRING |
+ CTLFLAG_RD, sc, 0, if_atsam_sysctl_tx_desc, "A",
+ "Transmit Descriptors");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rxdesc", CTLTYPE_STRING |
+ CTLFLAG_RD, sc, 0, if_atsam_sysctl_rx_desc, "A",
+ "Receive Descriptors");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "imr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_IMR), 0,
+ if_atsam_sysctl_reg, "I", "IMR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "isr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_ISR), 0,
+ if_atsam_sysctl_reg, "I", "ISR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "rsr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_RSR), 0,
+ if_atsam_sysctl_reg, "I", "RSR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "tsr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_TSR), 0,
+ if_atsam_sysctl_reg, "I", "TSR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "nsr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_NSR), 0,
+ if_atsam_sysctl_reg, "I", "NSR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ncfgr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_NCFGR), 0,
+ if_atsam_sysctl_reg, "I", "NCFGR");
+ SYSCTL_ADD_PROC(ctx, child, OID_AUTO, "ncr", CTLTYPE_UINT |
+ CTLFLAG_RD, __DEVOLATILE(uint32_t *, &pHw->GMAC_NCR), 0,
+ if_atsam_sysctl_reg, "I", "NCR");
+
+ tree = SYSCTL_ADD_NODE(ctx, base, OID_AUTO, "stats", CTLFLAG_RD,
NULL, "if_atsam statistics");
statsnode = SYSCTL_CHILDREN(tree);
+ SYSCTL_ADD_PROC(ctx, statsnode, OID_AUTO, "reset", CTLTYPE_INT |
+ CTLFLAG_WR, sc, 0, if_atsam_stats_reset, "I", "Reset");
+
tree = SYSCTL_ADD_NODE(ctx, statsnode, OID_AUTO, "sw", CTLFLAG_RD,
NULL, "if_atsam software statistics");
child = SYSCTL_CHILDREN(tree);
@@ -1145,12 +1299,12 @@ if_atsam_add_sysctls(device_t dev)
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_overrun_errors",
CTLFLAG_RD, &sc->stats.rx_overrun_errors, 0,
"RX overrun errors");
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_used_bit_reads",
+ CTLFLAG_RD, &sc->stats.rx_used_bit_reads, 0,
+ "RX used bit reads");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "rx_interrupts",
CTLFLAG_RD, &sc->stats.rx_interrupts, 0,
"Rx interrupts");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_complete_int",
- CTLFLAG_RD, &sc->stats.tx_complete_int, 0,
- "Tx complete interrupts");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_tur_errors",
CTLFLAG_RD, &sc->stats.tx_tur_errors, 0,
"Error Tur Tx interrupts");
@@ -1163,9 +1317,6 @@ if_atsam_add_sysctls(device_t dev)
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_hresp_errors",
CTLFLAG_RD, &sc->stats.tx_hresp_errors, 0,
"Error Hresp Tx interrupts");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "tx_interrupts",
- CTLFLAG_RD, &sc->stats.tx_interrupts, 0,
- "Tx interrupts");
tree = SYSCTL_ADD_NODE(ctx, statsnode, OID_AUTO, "hw", CTLFLAG_RD,
NULL, "if_atsam hardware statistics");
@@ -1175,40 +1326,40 @@ if_atsam_add_sysctls(device_t dev)
NULL, "if_atsam hardware transmit statistics");
child = SYSCTL_CHILDREN(tree);
- SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "octets_transm",
+ SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "octets",
CTLFLAG_RD, &sc->stats.octets_transm,
"Octets Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames",
CTLFLAG_RD, &sc->stats.frames_transm, 0,
"Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "broadcast_frames_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "broadcast_frames",
CTLFLAG_RD, &sc->stats.broadcast_frames_transm, 0,
"Broadcast Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "multicast_frames_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "multicast_frames",
CTLFLAG_RD, &sc->stats.multicast_frames_transm, 0,
"Multicast Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "pause_frames_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "pause_frames",
CTLFLAG_RD, &sc->stats.pause_frames_transm, 0,
"Pause Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_64_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_64_bytes",
CTLFLAG_RD, &sc->stats.frames_64_byte_transm, 0,
"64 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_65_to_127_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_65_to_127_bytes",
CTLFLAG_RD, &sc->stats.frames_65_to_127_byte_transm, 0,
"65 to 127 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_128_to_255_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_128_to_255_bytes",
CTLFLAG_RD, &sc->stats.frames_128_to_255_byte_transm, 0,
"128 to 255 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_256_to_511_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_256_to_511_bytes",
CTLFLAG_RD, &sc->stats.frames_256_to_511_byte_transm, 0,
"256 to 511 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_512_to_1023_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_512_to_1023_bytes",
CTLFLAG_RD, &sc->stats.frames_512_to_1023_byte_transm, 0,
"512 to 1023 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1024_to_1518_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1024_to_1518_bytes",
CTLFLAG_RD, &sc->stats.frames_1024_to_1518_byte_transm, 0,
"1024 to 1518 Byte Frames Transmitted");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_greater_1518_byte_transm",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1519_to_maximum_bytes",
CTLFLAG_RD, &sc->stats.frames_greater_1518_byte_transm, 0,
"Greater Than 1518 Byte Frames Transmitted");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "transmit_underruns",
@@ -1237,49 +1388,49 @@ if_atsam_add_sysctls(device_t dev)
NULL, "if_atsam hardware receive statistics");
child = SYSCTL_CHILDREN(tree);
- SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "octets_rec",
+ SYSCTL_ADD_UQUAD(ctx, child, OID_AUTO, "octets",
CTLFLAG_RD, &sc->stats.octets_rec,
"Octets Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames",
CTLFLAG_RD, &sc->stats.frames_rec, 0,
"Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "broadcast_frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "broadcast_frames",
CTLFLAG_RD, &sc->stats.broadcast_frames_rec, 0,
"Broadcast Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "multicast_frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "multicast_frames",
CTLFLAG_RD, &sc->stats.multicast_frames_rec, 0,
"Multicast Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "pause_frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "pause_frames",
CTLFLAG_RD, &sc->stats.pause_frames_rec, 0,
"Pause Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_64_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_64_bytes",
CTLFLAG_RD, &sc->stats.frames_64_byte_rec, 0,
"64 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_65_to_127_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_65_to_127_bytes",
CTLFLAG_RD, &sc->stats.frames_65_to_127_byte_rec, 0,
"65 to 127 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_128_to_255_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_128_to_255_bytes",
CTLFLAG_RD, &sc->stats.frames_128_to_255_byte_rec, 0,
"128 to 255 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_256_to_511_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_256_to_511_bytes",
CTLFLAG_RD, &sc->stats.frames_256_to_511_byte_rec, 0,
"256 to 511 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_512_to_1023_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_512_to_1023_bytes",
CTLFLAG_RD, &sc->stats.frames_512_to_1023_byte_rec, 0,
"512 to 1023 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1024_to_1518_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1024_to_1518_bytes",
CTLFLAG_RD, &sc->stats.frames_1024_to_1518_byte_rec, 0,
"1024 to 1518 Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1519_to_maximum_byte_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frames_1519_to_maximum_bytes",
CTLFLAG_RD, &sc->stats.frames_1519_to_maximum_byte_rec, 0,
"1519 to Maximum Byte Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "undersize_frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "undersize_frames",
CTLFLAG_RD, &sc->stats.undersize_frames_rec, 0,
"Undersize Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "oversize_frames_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "oversize_frames",
CTLFLAG_RD, &sc->stats.oversize_frames_rec, 0,
"Oversize Frames Received");
- SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "jabbers_rec",
+ SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "jabbers",
CTLFLAG_RD, &sc->stats.jabbers_rec, 0,
"Jabbers Received");
SYSCTL_ADD_UINT(ctx, child, OID_AUTO, "frame_check_sequence_errors",
@@ -1311,49 +1462,6 @@ if_atsam_add_sysctls(device_t dev)
"UDP Checksum Errors");
}
-
-/*
- * Calculates the index that is to be sent into the hash registers
- */
-static void if_atsam_get_hash_index(uint64_t addr, uint32_t *val)
-{
- uint64_t tmp_val;
- uint8_t i, j;
- uint64_t idx;
- int offset = 0;
-
- addr &= MAC_ADDR_MASK;
-
- for (i = 0; i < HASH_INDEX_AMOUNT; ++i) {
- tmp_val = 0;
- offset = 0;
- for (j = 0; j < HASH_ELEMENTS_PER_INDEX; j++) {
- idx = (addr >> (offset + i)) & MAC_IDX_MASK;
- tmp_val ^= idx;
- offset += HASH_INDEX_AMOUNT;
- }
- if (tmp_val > 0) {
- *val |= (1u << i);
- }
- }
-}
-
-
-/*
- * Dis/Enable promiscuous Mode
- */
-static void if_atsam_promiscuous_mode(if_atsam_softc *sc, bool enable)
-{
- Gmac *pHw = sc->Gmac_inst.gGmacd.pHw;
-
- if (enable) {
- pHw->GMAC_NCFGR |= GMAC_PROM_ENABLE;
- } else {
- pHw->GMAC_NCFGR &= ~GMAC_PROM_ENABLE;
- }
-}
-
-
static int
if_atsam_mediaioctl(if_atsam_softc *sc, struct ifreq *ifr, u_long command)
{
@@ -1380,8 +1488,6 @@ if_atsam_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
if_atsam_softc *sc = (if_atsam_softc *)ifp->if_softc;
struct ifreq *ifr = (struct ifreq *)data;
int rv = 0;
- bool prom_enable;
- struct mii_data *mii;
switch (command) {
case SIOCGIFMEDIA:
@@ -1389,17 +1495,31 @@ if_atsam_ioctl(struct ifnet *ifp, ioctl_command_t command, caddr_t data)
rv = if_atsam_mediaioctl(sc, ifr, command);
break;
case SIOCSIFFLAGS:
+ IF_ATSAM_LOCK(sc);
if (ifp->if_flags & IFF_UP) {
- if (!(ifp->if_drv_flags & IFF_DRV_RUNNING)) {
- if_atsam_init(sc);
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ if ((ifp->if_flags ^ sc->if_flags) &
+ (IFF_PROMISC | IFF_ALLMULTI)) {
+ if_atsam_setup_rxfilter(sc);
+ }
+ } else {
+ if_atsam_start_locked(sc);
}
- prom_enable = ((ifp->if_flags & IFF_PROMISC) != 0);
- if_atsam_promiscuous_mode(sc, prom_enable);
} else {
if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
- if_atsam_stop(sc);
+ if_atsam_stop_locked(sc);
}
}
+ sc->if_flags = ifp->if_flags;
+ IF_ATSAM_UNLOCK(sc);
+ break;
+ case SIOCADDMULTI:
+ case SIOCDELMULTI:
+ if (ifp->if_drv_flags & IFF_DRV_RUNNING) {
+ IF_ATSAM_LOCK(sc);
+ if_atsam_setup_rxfilter(sc);
+ IF_ATSAM_UNLOCK(sc);
+ }
break;
default:
rv = ether_ioctl(ifp, command, data);
@@ -1416,7 +1536,6 @@ static int if_atsam_driver_attach(device_t dev)
if_atsam_softc *sc;
struct ifnet *ifp;
int unit;
- char *unitName;
uint8_t eaddr[ETHER_ADDR_LEN];
sc = device_get_softc(dev);
@@ -1437,13 +1556,6 @@ static int if_atsam_driver_attach(device_t dev)
memcpy(sc->GMacAddress, eaddr, ETHER_ADDR_LEN);
- sc->amount_rx_buf = RXBUF_COUNT;
- sc->amount_tx_buf = TXBUF_COUNT;
-
- sc->tx_ring.tx_bd_used = 0;
- sc->tx_ring.tx_bd_free = 0;
- sc->tx_ring.length = sc->amount_tx_buf;
-
/* Set Initial Link Speed */
sc->link_speed = GMAC_SPEED_100M;
sc->link_duplex = GMAC_DUPLEX_FULL;
@@ -1486,17 +1598,20 @@ static int if_atsam_driver_attach(device_t dev)
*/
ifp->if_softc = sc;
if_initname(ifp, device_get_name(dev), device_get_unit(dev));
- ifp->if_init = if_atsam_init;
+ ifp->if_init = if_atsam_start;
ifp->if_ioctl = if_atsam_ioctl;
- ifp->if_start = if_atsam_enet_start;
- ifp->if_flags = IFF_BROADCAST | IFF_SIMPLEX;
+ ifp->if_transmit = if_atsam_transmit;
+ ifp->if_qflush = if_qflush;
+ ifp->if_flags = IFF_BROADCAST | IFF_MULTICAST | IFF_SIMPLEX;
ifp->if_capabilities |= IFCAP_HWCSUM | IFCAP_HWCSUM_IPV6 |
- IFCAP_VLAN_HWCSUM;
+ IFCAP_VLAN_HWCSUM | IFCAP_VLAN_HWTAGGING;
+ ifp->if_capenable = ifp->if_capabilities;
ifp->if_hwassist = CSUM_IP | CSUM_IP_UDP | CSUM_IP_TCP |
CSUM_IP6_UDP | CSUM_IP6_TCP;
- IFQ_SET_MAXLEN(&ifp->if_snd, TXBUF_COUNT - 1);
- ifp->if_snd.ifq_drv_maxlen = TXBUF_COUNT - 1;
+ IFQ_SET_MAXLEN(&ifp->if_snd, TX_DESC_COUNT - 1);
+ ifp->if_snd.ifq_drv_maxlen = TX_DESC_COUNT - 1;
IFQ_SET_READY(&ifp->if_snd);
+ ifp->if_hdrlen = sizeof(struct ether_vlan_header);
/*
* Attach the interface
@@ -1504,6 +1619,7 @@ static int if_atsam_driver_attach(device_t dev)
ether_ifattach(ifp, eaddr);
if_atsam_add_sysctls(dev);
+ if_atsam_init(sc);
return (0);
}
diff --git a/rtemsbsd/sys/dev/nvd/nvd.c b/rtemsbsd/sys/dev/nvd/nvd.c
index 897b0af6..4a8e8ac1 100644
--- a/rtemsbsd/sys/dev/nvd/nvd.c
+++ b/rtemsbsd/sys/dev/nvd/nvd.c
@@ -43,6 +43,7 @@
#include <stdatomic.h>
#include <rtems/blkdev.h>
+#include <rtems/thread.h>
#define NVD_STR "nvd"
@@ -164,10 +165,9 @@ nvd_completion(void *arg, const struct nvme_completion *status)
static int
nvd_request(struct nvd_disk *ndisk, rtems_blkdev_request *req,
- uint32_t media_blocks_per_block)
+ uint32_t media_block_size)
{
uint32_t i;
- uint32_t lb_count;
uint32_t bufnum;
BSD_ASSERT(req->req == RTEMS_BLKDEV_REQ_READ ||
@@ -178,13 +178,15 @@ nvd_request(struct nvd_disk *ndisk, rtems_blkdev_request *req,
req->status = RTEMS_SUCCESSFUL;
bufnum = req->bufnum;
req->bufnum |= bufnum << NVD_BUFNUM_SHIFT;
- lb_count = media_blocks_per_block * ndisk->lb_per_media_block;
for (i = 0; i < bufnum; ++i) {
rtems_blkdev_sg_buffer *sg;
+ uint32_t lb_count;
int error;
sg = &req->bufs[i];
+ lb_count = (sg->length / media_block_size) *
+ ndisk->lb_per_media_block;
if (req->req == RTEMS_BLKDEV_REQ_READ) {
error = nvme_ns_cmd_read(ndisk->ns, sg->buffer,
@@ -208,28 +210,27 @@ nvd_request(struct nvd_disk *ndisk, rtems_blkdev_request *req,
static void
nvd_sync_completion(void *arg, const struct nvme_completion *status)
{
- rtems_status_code sc;
-
- if (nvme_completion_is_error(status)) {
- sc = RTEMS_IO_ERROR;
- } else {
- sc = RTEMS_SUCCESSFUL;
- }
+ rtems_binary_semaphore *sync;
- rtems_blkdev_request_done(arg, sc);
+ sync = arg;
+ rtems_binary_semaphore_post(sync);
}
static int
-nvd_sync(struct nvd_disk *ndisk, rtems_blkdev_request *req)
+nvd_sync(struct nvd_disk *ndisk)
{
+ rtems_binary_semaphore sync;
int error;
- error = nvme_ns_cmd_flush(ndisk->ns, nvd_sync_completion, req);
- if (error != 0) {
- rtems_blkdev_request_done(req, RTEMS_NO_MEMORY);
+ rtems_binary_semaphore_init(&sync, "nvd sync");
+
+ error = nvme_ns_cmd_flush(ndisk->ns, nvd_sync_completion, &sync);
+ if (error == 0) {
+ rtems_binary_semaphore_wait(&sync);
}
- return (0);
+ rtems_binary_semaphore_destroy(&sync);
+ return (error);
}
static int
@@ -240,11 +241,11 @@ nvd_ioctl(rtems_disk_device *dd, uint32_t req, void *arg)
ndisk = rtems_disk_get_driver_data(dd);
if (req == RTEMS_BLKIO_REQUEST) {
- return (nvd_request(ndisk, arg, dd->media_blocks_per_block));
+ return (nvd_request(ndisk, arg, dd->media_block_size));
}
if (req == RTEMS_BLKDEV_REQ_SYNC) {
- return (nvd_sync(ndisk, arg));
+ return (nvd_sync(ndisk));
}
if (req == RTEMS_BLKIO_CAPABILITIES) {
diff --git a/rtemsbsd/sys/net/if_ppp.c b/rtemsbsd/sys/net/if_ppp.c
index 709f13e0..e134dc76 100644
--- a/rtemsbsd/sys/net/if_ppp.c
+++ b/rtemsbsd/sys/net/if_ppp.c
@@ -313,11 +313,12 @@ static rtems_task ppp_txdaemon(rtems_task_argument arg)
frag=0;
/* initialize output values */
- sc->sc_outfcs = PPP_INITFCS;
- sc->sc_outbuf = (u_char *)0;
- sc->sc_outlen = (short )0;
- sc->sc_outoff = (short )0;
- sc->sc_outfcslen = (short )0;
+ sc->sc_outfcs = PPP_INITFCS;
+ sc->sc_outbuf = (u_char *)0;
+ sc->sc_outlen = (short )0;
+ sc->sc_outoff = (short )0;
+ sc->sc_outoff_update = false;
+ sc->sc_outfcslen = (short )0;
/* printf("Start Transmit Packet..\n"); */
diff --git a/rtemsbsd/sys/net/if_pppvar.h b/rtemsbsd/sys/net/if_pppvar.h
index fdfb56df..bd11bcbc 100644
--- a/rtemsbsd/sys/net/if_pppvar.h
+++ b/rtemsbsd/sys/net/if_pppvar.h
@@ -117,6 +117,7 @@ struct ppp_softc {
struct ifqueue sc_freeq; /* free packets */
short sc_outoff; /* output packet byte offset */
+ bool sc_outoff_update; /* outoff needs update in pppstart */
short sc_outflag; /* output status flag */
short sc_outlen; /* length of output packet */
short sc_outfcslen; /* length of output fcs data */
diff --git a/rtemsbsd/sys/net/ppp_tty.c b/rtemsbsd/sys/net/ppp_tty.c
index 80d4fee1..2e850dc7 100644
--- a/rtemsbsd/sys/net/ppp_tty.c
+++ b/rtemsbsd/sys/net/ppp_tty.c
@@ -124,7 +124,7 @@ int pppread(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args);
int pppwrite(struct rtems_termios_tty *tty, rtems_libio_rw_args_t *rw_args);
int ppptioctl(struct rtems_termios_tty *tty, rtems_libio_ioctl_args_t *args);
int pppinput(int c, struct rtems_termios_tty *tty);
-int pppstart(struct rtems_termios_tty *tp);
+int pppstart(struct rtems_termios_tty *tp, int len);
u_short pppfcs(u_short fcs, u_char *cp, int len);
void pppallocmbuf(struct ppp_softc *sc, struct mbuf **mp);
@@ -557,7 +557,7 @@ pppasyncctlp(
* Called at spltty or higher.
*/
int
-pppstart(struct rtems_termios_tty *tp)
+pppstart(struct rtems_termios_tty *tp, int len)
{
u_char *sendBegin;
u_long ioffset = (u_long )0;
@@ -567,6 +567,13 @@ pppstart(struct rtems_termios_tty *tp)
/* ensure input is valid and we are busy */
if (( sc != NULL ) && ( sc->sc_outflag & SC_TX_BUSY )) {
+ /* Adapt offsets if necessary */
+ if ( sc->sc_outoff_update ) {
+ sc->sc_stats.ppp_obytes += len;
+ sc->sc_outoff += len;
+ sc->sc_outoff_update = false;
+ }
+
/* check to see if we need to get the next buffer */
/* Ready with PPP_FLAG Character ? */
@@ -644,8 +651,25 @@ pppstart(struct rtems_termios_tty *tp)
/* write out the character(s) and update the stats */
(*tp->handler.write)(ctx, (char *)sendBegin, (ioffset > 0) ? ioffset : 1);
- sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
- sc->sc_outoff += ioffset;
+ /*
+ * In case of polled drivers, everything is sent here. So adapt the
+ * offsets. In case of interrupt or task driven drivers, we don't know
+ * whether all characters have been sent. We only get feedback via
+ * rtems_termios_dequeue_characters() function which is the one that is
+ * calling us.
+ */
+ if (tp->handler.mode == TERMIOS_POLLED) {
+ sc->sc_stats.ppp_obytes += (ioffset > 0) ? ioffset : 1;
+ sc->sc_outoff += ioffset;
+ sc->sc_outoff_update = false;
+ } else {
+ if (ioffset > 0) {
+ sc->sc_outoff_update = true;
+ } else {
+ sc->sc_outoff_update = false;
+ sc->sc_stats.ppp_obytes += 1;
+ }
+ }
return (0);
}
diff --git a/testsuite/mcast01/test_main.c b/testsuite/mcast01/test_main.c
new file mode 100644
index 00000000..ad6c45b7
--- /dev/null
+++ b/testsuite/mcast01/test_main.c
@@ -0,0 +1,286 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @brief Example code to test multicasts.
+ *
+ * ping 224.0.0.1
+ *
+ * Linux:
+ *
+ * echo 0 > /proc/sys/net/ipv4/icmp_echo_ignore_broadcasts
+ * echo 1 > /proc/sys/net/ipv4/ip_forward
+ * ip route add 224.0.0.0/4 dev eth0
+ * echo "Hello, world!" > /dev/udp/239.1.2.3/1234
+ */
+
+/*
+ * Copyright (C) 2020 embedded brains GmbH (http://www.embedded-brains.de)
+ *
+ * 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 COPYRIGHT HOLDERS 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 COPYRIGHT OWNER 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/param.h>
+#include <sys/socket.h>
+#include <sys/sysctl.h>
+
+#include <assert.h>
+#include <inttypes.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sysexits.h>
+
+#include <arpa/inet.h>
+#include <netinet/in.h>
+
+#include <machine/rtems-bsd-commands.h>
+
+#include <rtems/console.h>
+#include <rtems/shell.h>
+#include <rtems/dhcpcd.h>
+
+#define TEST_NAME "LIBBSD MCAST 1"
+#define TEST_STATE_USER_INPUT 1
+
+#define MCAST_PORT 1234
+
+#define MAX_PACKET_SIZE UINT16_MAX
+
+static const char mcast_addr[] = "239.1.2.3";
+
+static const char hello[] = "Hello, world!";
+
+typedef struct {
+ in_addr_t addr;
+ char name[];
+} iface_binding;
+
+static void
+set_mcast_route(char *iface_name)
+{
+ static char net[] = "224.0.0.0/4";
+ int exit_code;
+ char *route[] = {
+ "route",
+ "add",
+ "-net",
+ net,
+ "-iface",
+ iface_name,
+ NULL
+ };
+
+ exit_code = rtems_bsd_command_route(RTEMS_BSD_ARGC(route), route);
+ assert(exit_code == EXIT_SUCCESS);
+}
+
+static void
+mcast_rx_task(rtems_task_argument arg)
+{
+ iface_binding *ifb;
+ struct ip_mreq mreq;
+ int sd;
+ struct sockaddr_in addr;
+ int rv;
+ char addr_buf[INET_ADDRSTRLEN];
+ const char *ip;
+ ssize_t n;
+
+ ifb = (iface_binding *)arg;
+ set_mcast_route(ifb->name);
+
+ memset(&addr, 0, sizeof(addr));
+ addr.sin_family = AF_INET;
+ addr.sin_addr.s_addr = ifb->addr;
+
+ ip = inet_ntop(AF_INET, &addr.sin_addr, addr_buf, sizeof(addr_buf));
+ printf("mcast: join %s using interface IP %s\n", mcast_addr, ip);
+
+ sd = socket(PF_INET, SOCK_DGRAM, IPPROTO_UDP);
+ assert(sd >= 0);
+
+ addr.sin_port = htons(MCAST_PORT);
+ addr.sin_addr.s_addr = INADDR_ANY;
+
+ rv = bind(sd, (const struct sockaddr *)&addr, sizeof(addr));
+ assert(rv == 0);
+
+ memset(&mreq, 0, sizeof(mreq));
+ mreq.imr_multiaddr.s_addr = inet_addr(mcast_addr);
+ mreq.imr_interface.s_addr = ifb->addr;
+
+ rv = setsockopt(sd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq));
+ assert(rv == 0);
+
+ addr.sin_family = AF_INET;
+ addr.sin_port = htons(MCAST_PORT);
+ addr.sin_addr.s_addr = inet_addr(mcast_addr);
+ n = sendto(sd, hello, sizeof(hello), 0,
+ (const struct sockaddr *)&addr, sizeof(addr));
+
+ if (n != (ssize_t)sizeof(hello)) {
+ perror("send");
+ }
+
+ while (true) {
+ socklen_t addr_len;
+ char buf[MAX_PACKET_SIZE];
+
+ addr_len = sizeof(addr);
+ n = recvfrom(sd, buf, sizeof(buf), 0,
+ (struct sockaddr *)&addr, &addr_len);
+ if (n >= 0 && addr.sin_addr.s_addr != ifb->addr) {
+ size_t m;
+ ip = inet_ntop(AF_INET, &addr.sin_addr, addr_buf,
+ sizeof(addr_buf));
+ printf("mcast: received %zi bytes from %s\n", n, ip);
+
+ addr.sin_port = htons(MCAST_PORT);
+ addr.sin_addr.s_addr = inet_addr(mcast_addr);
+ m = (size_t)n;
+ n = sendto(sd, buf, m, 0,
+ (const struct sockaddr *)&addr,
+ sizeof(addr));
+ assert(n == (ssize_t)m);
+ } else if (n < 0 ) {
+ perror("recvfrom");
+ }
+ }
+}
+
+static void
+start_mcast_rx(const char *iface_ip, const char *iface_name)
+{
+ rtems_status_code sc;
+ rtems_id id;
+ iface_binding *ifb;
+ size_t len;
+
+ len = strlen(iface_name) + 1;
+ ifb = malloc(sizeof(*ifb) + len);
+ assert(ifb != NULL);
+ ifb->addr = inet_addr(iface_ip);
+ memcpy(ifb->name, iface_name, len);
+
+ sc = rtems_task_create(rtems_build_name('M', 'C', 'R', 'X'),
+ RTEMS_MINIMUM_PRIORITY, RTEMS_MINIMUM_STACK_SIZE + MAX_PACKET_SIZE,
+ RTEMS_DEFAULT_MODES, RTEMS_FLOATING_POINT, &id);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(id, mcast_rx_task, (rtems_task_argument)ifb);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static const char *
+get_value(char *const *env, const char *key)
+{
+ size_t len;
+
+ len = strlen(key);
+
+ while (true) {
+ const char *s;
+
+ s = *env;
+
+ if (s == NULL) {
+ return "";
+ }
+
+ if (strncmp(key, s, len) == 0 && s[len] == '=') {
+ return &s[len + 1];
+ }
+
+ ++env;
+ }
+}
+
+static void
+dhcpcd_hook_handler(rtems_dhcpcd_hook *hook, char *const *env)
+{
+
+ (void)hook;
+
+ if (strcmp(get_value(env, "reason"), "BOUND") == 0) {
+ start_mcast_rx(get_value(env, "new_ip_address"),
+ get_value(env, "interface"));
+ }
+}
+
+static rtems_dhcpcd_hook dhcpcd_hook = {
+ .name = "mcast",
+ .handler = dhcpcd_hook_handler
+};
+
+static void
+test_main(void)
+{
+ rtems_status_code sc;
+ int enable;
+ int rv;
+
+ rtems_dhcpcd_add_hook(&dhcpcd_hook);
+
+ enable = 1;
+ rv = sysctlbyname("net.inet.icmp.bmcastecho", NULL, NULL, &enable,
+ sizeof(enable));
+ assert(rv == 0);
+
+ sc = rtems_shell_init("SHLL", 16 * 1024, 1, CONSOLE_DEVICE_NAME,
+ false, true, NULL);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ exit(0);
+}
+
+#define DEFAULT_NETWORK_DHCPCD_ENABLE
+
+#include <rtems/bsd/test/default-network-init.h>
+
+#define CONFIGURE_SHELL_COMMANDS_INIT
+
+#include <bsp/irq-info.h>
+
+#include <rtems/netcmds-config.h>
+
+#define CONFIGURE_SHELL_USER_COMMANDS \
+ &bsp_interrupt_shell_command, \
+ &rtems_shell_ARP_Command, \
+ &rtems_shell_HOSTNAME_Command, \
+ &rtems_shell_PING_Command, \
+ &rtems_shell_ROUTE_Command, \
+ &rtems_shell_NETSTAT_Command, \
+ &rtems_shell_SYSCTL_Command, \
+ &rtems_shell_IFCONFIG_Command, \
+ &rtems_shell_IFMCSTAT_Command, \
+ &rtems_shell_VMSTAT_Command
+
+#define CONFIGURE_SHELL_COMMAND_CPUINFO
+#define CONFIGURE_SHELL_COMMAND_CPUUSE
+#define CONFIGURE_SHELL_COMMAND_PERIODUSE
+#define CONFIGURE_SHELL_COMMAND_STACKUSE
+#define CONFIGURE_SHELL_COMMAND_MALLOC_INFO
+
+#include <rtems/shellconfig.h>
diff --git a/testsuite/media01/test_main.c b/testsuite/media01/test_main.c
index 91e0dd5a..dcab3220 100644
--- a/testsuite/media01/test_main.c
+++ b/testsuite/media01/test_main.c
@@ -123,7 +123,7 @@ telnet_shell(char *name, void *arg)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
env.devname = name;
env.taskname = "TLNT";
@@ -240,6 +240,7 @@ early_initialization(void)
&rtems_shell_NETSTAT_Command, \
&rtems_shell_SYSCTL_Command, \
&rtems_shell_IFCONFIG_Command, \
+ &rtems_shell_IFMCSTAT_Command, \
&rtems_shell_VMSTAT_Command
#define CONFIGURE_SHELL_COMMAND_CPUINFO
diff --git a/testsuite/netshell01/test_main.c b/testsuite/netshell01/test_main.c
index 81941d0b..b967cb87 100644
--- a/testsuite/netshell01/test_main.c
+++ b/testsuite/netshell01/test_main.c
@@ -162,7 +162,7 @@ test_main(void)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
rtems_shell_main_loop(&env);
exit(0);
diff --git a/testsuite/pf02/test_main.c b/testsuite/pf02/test_main.c
index 92073165..dfb9847b 100644
--- a/testsuite/pf02/test_main.c
+++ b/testsuite/pf02/test_main.c
@@ -132,7 +132,7 @@ telnet_shell(char *name, void *arg)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
env.devname = name;
env.taskname = "TLNT";
@@ -167,6 +167,7 @@ test_main(void)
{
rtems_status_code sc;
int rv;
+ rtems_shell_env_t env;
prepare_files();
@@ -176,9 +177,7 @@ test_main(void)
rv = rtems_initialize_ftpd();
assert(rv == 0);
- rtems_shell_env_t env;
-
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
rtems_shell_main_loop( &env );
exit(0);
diff --git a/testsuite/ppp01/test_main.c b/testsuite/ppp01/test_main.c
index 078e96e2..d4baf5db 100644
--- a/testsuite/ppp01/test_main.c
+++ b/testsuite/ppp01/test_main.c
@@ -211,7 +211,7 @@ telnet_shell(char *name, void *arg)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
env.devname = name;
env.taskname = "TLNT";
diff --git a/testsuite/tcpdump01/test_main.c b/testsuite/tcpdump01/test_main.c
new file mode 100644
index 00000000..0f31cdde
--- /dev/null
+++ b/testsuite/tcpdump01/test_main.c
@@ -0,0 +1,292 @@
+/* SPDX-License-Identifier: BSD-2-Clause */
+
+/**
+ * @file
+ *
+ * @brief Tests the tcpdump command.
+ */
+
+/*
+ * Copyright (C) 2022 embedded brains GmbH
+ *
+ * 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>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <vm/uma.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+#include <err.h>
+
+#include <assert.h>
+#include <ck_epoch.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+
+#include <rtems.h>
+#include <rtems/bsd/bsd.h>
+#include <rtems/console.h>
+#include <rtems/libcsupport.h>
+
+#include <machine/rtems-bsd-commands.h>
+
+#define TEST_NAME "LIBBSD TCPDUMP 1"
+
+typedef struct {
+ rtems_id main_id;
+ int sp[2];
+} test_context;
+
+static test_context test_instance;
+
+static void
+epoch_cleanup(void)
+{
+ rtems_status_code sc;
+
+ sc = rtems_task_wake_after(CK_EPOCH_LENGTH);
+ assert(sc == RTEMS_SUCCESSFUL);
+}
+
+static void
+init_addr(struct sockaddr_in *addr)
+{
+ int ok;
+
+ memset(addr, 0, sizeof(*addr));
+ addr->sin_family = AF_INET;
+ addr->sin_port = htons(1234);
+ ok = inet_aton("127.0.0.1", &addr->sin_addr);
+ assert(ok != 0);
+}
+
+static rtems_id
+start_task(rtems_task_entry entry, void *arg)
+{
+ rtems_task_priority prio;
+ rtems_id id;
+ rtems_status_code sc;
+
+ sc = rtems_task_set_priority(RTEMS_SELF, RTEMS_CURRENT_PRIORITY, &prio);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_create(rtems_build_name('T', 'E', 'S', 'T' ), prio - 1,
+ 32 * 1024, RTEMS_DEFAULT_MODES, RTEMS_DEFAULT_ATTRIBUTES, &id);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ sc = rtems_task_start(id, entry, (rtems_task_argument)arg);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ return id;
+}
+
+static void
+test_tcpdump_help(void)
+{
+ char *argv[] = {
+ "tcpdump",
+ "-h",
+ NULL
+ };
+ rtems_resource_snapshot snapshot;
+ int exit_code;
+
+ rtems_resource_snapshot_take(&snapshot);
+
+ exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv);
+ assert(exit_code == 0);
+
+ assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static const char raw_packets_file[] = "packets.bin";
+
+static void
+run_tcpdump_write_raw_packets(rtems_task_argument arg)
+{
+ test_context *ctx;
+ FILE *file;
+ FILE *saved_stdin;
+ FILE *saved_stdout;
+ FILE *saved_stderr;
+ int rv;
+ char *argv[] = {
+ "tcpdump",
+ "-n",
+ "-i",
+ "lo0",
+ "-w",
+ RTEMS_DECONST(char *, raw_packets_file),
+ NULL
+ };
+ int exit_code;
+ rtems_status_code sc;
+
+ ctx = (test_context *)arg;
+
+ saved_stdin = stdin;
+ saved_stdout = stdout;
+ saved_stderr = stderr;
+
+ file = fdopen(ctx->sp[1], "r+");
+ assert(file != NULL);
+
+ stdin = file;
+ stdout = file;
+ stderr = file;
+
+ exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv);
+ assert(exit_code == 0);
+
+ stdin = saved_stdin;
+ stdout = saved_stdout;
+ stderr = saved_stderr;
+
+ rv = fclose(file);
+ assert(rv == 0);
+
+ sc = rtems_event_transient_send(ctx->main_id);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ rtems_task_exit();
+}
+
+static void
+test_tcpdump_write_raw_packets(test_context *ctx)
+{
+ char *argv[] = {
+ "tcpdump",
+ "-n",
+ "-r",
+ RTEMS_DECONST(char *, raw_packets_file),
+ NULL
+ };
+ rtems_resource_snapshot snapshot;
+ int in;
+ int out;
+ int rv;
+ char c;
+ ssize_t n;
+ struct sockaddr_in addr;
+ socklen_t addr_len;
+ rtems_status_code sc;
+ int exit_code;
+
+ rtems_resource_snapshot_take(&snapshot);
+
+ rv = socketpair(PF_UNIX, SOCK_STREAM, 0, ctx->sp);
+ assert(rv == 0);
+
+ start_task(run_tcpdump_write_raw_packets, ctx);
+
+ init_addr(&addr);
+
+ in = socket(PF_INET, SOCK_DGRAM, 0);
+ assert(out >= 0);
+
+ rv = bind(in, (const struct sockaddr *) &addr, sizeof(addr));
+ assert(rv == 0);
+
+ out = socket(PF_INET, SOCK_DGRAM, 0);
+ assert(out >= 0);
+
+ c = 'x';
+ n = sendto(out, &c, sizeof(c), 0,
+ (const struct sockaddr *) &addr, sizeof(addr));
+ assert(n == 1);
+
+ c = 'y';
+ addr_len = sizeof(addr);
+ n = recvfrom(in, &c, sizeof(c), 0,
+ (struct sockaddr *) &addr, &addr_len);
+ assert(n == 1);
+ assert(c == 'x');
+
+ /* The tcpdump pcap read timeout is 1000ms */
+ sc = rtems_task_wake_after(rtems_clock_get_ticks_per_second());
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ c = 'q';
+ n = write(ctx->sp[0], &c, sizeof(c));
+ assert(n == 1);
+
+ rv = close(out);
+ assert(rv == 0);
+
+ rv = close(in);
+ assert(rv == 0);
+
+ sc = rtems_event_transient_receive(RTEMS_WAIT, RTEMS_NO_TIMEOUT);
+ assert(sc == RTEMS_SUCCESSFUL);
+
+ rv = close(ctx->sp[0]);
+ assert(rv == 0);
+
+ exit_code = rtems_bsd_command_tcpdump(RTEMS_BSD_ARGC(argv), argv);
+ assert(exit_code == 0);
+
+ rv = unlink(raw_packets_file);
+ assert(rv == 0);
+
+ epoch_cleanup();
+ assert(rtems_resource_snapshot_check(&snapshot));
+}
+
+static void
+test_main(void)
+{
+ test_context *ctx;
+ FILE *file;
+ int rv;
+
+ ctx = &test_instance;
+ ctx->main_id = rtems_task_self();
+
+ /* Fill dynamic file pool in Newlib */
+ file = fopen(CONSOLE_DEVICE_NAME, "r+");
+ assert(file != NULL);
+ rv = fclose(file);
+ assert(rv == 0);
+
+ /*
+ * Stop interferences of uma_timeout() which may need some dynamic
+ * memory.
+ */
+ rtems_uma_drain_timeout();
+
+ rtems_bsd_ifconfig_lo0();
+ epoch_cleanup();
+
+ test_tcpdump_help();
+ test_tcpdump_write_raw_packets(ctx);
+
+ exit(0);
+}
+
+#include <rtems/bsd/test/default-init.h>
diff --git a/testsuite/telnetd01/test_main.c b/testsuite/telnetd01/test_main.c
index 00916843..73d19c4e 100644
--- a/testsuite/telnetd01/test_main.c
+++ b/testsuite/telnetd01/test_main.c
@@ -50,7 +50,7 @@ telnet_shell(char *name, void *arg)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
env.devname = name;
env.taskname = "TLNT";
diff --git a/testsuite/zerocopy01/test_main.c b/testsuite/zerocopy01/test_main.c
index 3e7b7b7b..1be546e4 100644
--- a/testsuite/zerocopy01/test_main.c
+++ b/testsuite/zerocopy01/test_main.c
@@ -190,7 +190,7 @@ telnet_shell(char *name, void *arg)
{
rtems_shell_env_t env;
- memset(&env, 0, sizeof(env));
+ rtems_shell_dup_current_env(&env);
env.devname = name;
env.taskname = "TLNT";
diff --git a/waf_libbsd.py b/waf_libbsd.py
index 310a6924..6d0e5e73 100644
--- a/waf_libbsd.py
+++ b/waf_libbsd.py
@@ -495,17 +495,24 @@ class Builder(builder.ModuleManager):
if 'header-paths' in config:
headerPaths = config['header-paths']
cpu = bld.get_env()['RTEMS_ARCH']
- if cpu == "i386":
- cpu = 'x86'
for headers in headerPaths:
- # Get the dest path
- ipath = os.path.join(arch_inc_path, headers[2])
- start_dir = bld.path.find_dir(headers[0].replace('@CPU@', cpu))
- if start_dir != None:
- bld.install_files("${PREFIX}/" + ipath,
- start_dir.ant_glob(headers[1]),
- cwd = start_dir,
- relative_trick = True)
+ paths = [headers[0].replace('@CPU@', cpu)]
+ # Apply the path mappings
+ for source, targets in config['path-mappings']:
+ if source in paths:
+ i = paths.index(source)
+ paths.remove(source)
+ paths[i:i] = targets
+
+ for hp in paths:
+ # Get the dest path
+ ipath = os.path.join(arch_inc_path, headers[2])
+ start_dir = bld.path.find_dir(hp)
+ if start_dir != None:
+ bld.install_files("${PREFIX}/" + ipath,
+ start_dir.ant_glob(headers[1]),
+ cwd=start_dir,
+ relative_trick=True)
bld.install_files(os.path.join("${PREFIX}", arch_inc_path,
module_header_path),