diff options
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 @@ -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()); @@ -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), |