MFhead @ r277659
This commit is contained in:
commit
bfd71a93e3
@ -1460,6 +1460,9 @@ _elftctools= lib/libelftc \
|
||||
usr.bin/nm \
|
||||
usr.bin/size \
|
||||
usr.bin/strings
|
||||
# These are not required by the build, but can be useful for developers who
|
||||
# cross-build on a FreeBSD 10 host:
|
||||
_elftctools+= usr.bin/addr2line
|
||||
.endif
|
||||
.endif
|
||||
|
||||
|
@ -330,7 +330,7 @@ copy_special(struct stat *from_stat, int exists)
|
||||
int
|
||||
setfile(struct stat *fs, int fd)
|
||||
{
|
||||
static struct timeval tv[2];
|
||||
static struct timespec tspec[2];
|
||||
struct stat ts;
|
||||
int rval, gotstat, islink, fdval;
|
||||
|
||||
@ -340,10 +340,11 @@ setfile(struct stat *fs, int fd)
|
||||
fs->st_mode &= S_ISUID | S_ISGID | S_ISVTX |
|
||||
S_IRWXU | S_IRWXG | S_IRWXO;
|
||||
|
||||
TIMESPEC_TO_TIMEVAL(&tv[0], &fs->st_atim);
|
||||
TIMESPEC_TO_TIMEVAL(&tv[1], &fs->st_mtim);
|
||||
if (islink ? lutimes(to.p_path, tv) : utimes(to.p_path, tv)) {
|
||||
warn("%sutimes: %s", islink ? "l" : "", to.p_path);
|
||||
tspec[0] = fs->st_atim;
|
||||
tspec[1] = fs->st_mtim;
|
||||
if (utimensat(AT_FDCWD, to.p_path, tspec,
|
||||
islink ? AT_SYMLINK_NOFOLLOW : 0)) {
|
||||
warn("utimensat: %s", to.p_path);
|
||||
rval = 1;
|
||||
}
|
||||
if (fdval ? fstat(fd, &ts) :
|
||||
|
@ -29,7 +29,7 @@
|
||||
.\" @(#)symlink.7 8.3 (Berkeley) 3/31/94
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd December 29, 2014
|
||||
.Dd January 23, 2015
|
||||
.Dt SYMLINK 7
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -147,9 +147,10 @@ unless given the
|
||||
.Dv AT_SYMLINK_NOFOLLOW
|
||||
flag:
|
||||
.Xr fchmodat 2 ,
|
||||
.Xr fchownat 2
|
||||
.Xr fchownat 2 ,
|
||||
.Xr fstatat 2
|
||||
and
|
||||
.Xr fstatat 2 .
|
||||
.Xr utimensat 2 .
|
||||
.Pp
|
||||
The owner and group of an existing symbolic link can be changed by
|
||||
means of the
|
||||
|
@ -273,7 +273,7 @@ do_move(const char *from, const char *to)
|
||||
static int
|
||||
fastcopy(const char *from, const char *to, struct stat *sbp)
|
||||
{
|
||||
struct timeval tval[2];
|
||||
struct timespec ts[2];
|
||||
static u_int blen = MAXPHYS;
|
||||
static char *bp = NULL;
|
||||
mode_t oldmode;
|
||||
@ -350,10 +350,9 @@ err: if (unlink(to))
|
||||
} else
|
||||
warn("%s: cannot stat", to);
|
||||
|
||||
tval[0].tv_sec = sbp->st_atime;
|
||||
tval[1].tv_sec = sbp->st_mtime;
|
||||
tval[0].tv_usec = tval[1].tv_usec = 0;
|
||||
if (utimes(to, tval))
|
||||
ts[0] = sbp->st_atim;
|
||||
ts[1] = sbp->st_mtim;
|
||||
if (utimensat(AT_FDCWD, to, ts, 0))
|
||||
warn("%s: set times", to);
|
||||
|
||||
if (close(to_fd)) {
|
||||
|
@ -432,15 +432,16 @@ get_core_register_section (char *name,
|
||||
char *human_name,
|
||||
int required)
|
||||
{
|
||||
char section_name[100];
|
||||
static char *section_name = NULL;
|
||||
struct bfd_section *section;
|
||||
bfd_size_type size;
|
||||
char *contents;
|
||||
|
||||
xfree (section_name);
|
||||
if (PIDGET (inferior_ptid))
|
||||
sprintf (section_name, "%s/%d", name, PIDGET (inferior_ptid));
|
||||
section_name = xstrprintf ("%s/%d", name, PIDGET (inferior_ptid));
|
||||
else
|
||||
strcpy (section_name, name);
|
||||
section_name = xstrdup (name);
|
||||
|
||||
section = bfd_get_section_by_name (core_bfd, section_name);
|
||||
if (! section)
|
||||
|
@ -575,6 +575,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
||||
break;
|
||||
case DW_OP_div:
|
||||
binop = BINOP_DIV;
|
||||
break;
|
||||
case DW_OP_minus:
|
||||
binop = BINOP_SUB;
|
||||
break;
|
||||
@ -595,6 +596,7 @@ execute_stack_op (struct dwarf_expr_context *ctx, unsigned char *op_ptr,
|
||||
break;
|
||||
case DW_OP_shr:
|
||||
binop = BINOP_RSH;
|
||||
break;
|
||||
case DW_OP_shra:
|
||||
binop = BINOP_RSH;
|
||||
val1 = value_from_longest (signed_address_type (), first);
|
||||
|
@ -3463,7 +3463,7 @@ remote_store_registers (int regnum)
|
||||
{
|
||||
int i;
|
||||
regs = alloca (rs->sizeof_g_packet);
|
||||
memset (regs, rs->sizeof_g_packet, 0);
|
||||
memset (regs, 0, rs->sizeof_g_packet);
|
||||
for (i = 0; i < NUM_REGS + NUM_PSEUDO_REGS; i++)
|
||||
{
|
||||
struct packet_reg *r = &rs->regs[i];
|
||||
|
@ -61,7 +61,7 @@ value_of_builtin_frame_reg (struct frame_info *frame)
|
||||
val = allocate_value (builtin_type_frame_reg);
|
||||
VALUE_LVAL (val) = not_lval;
|
||||
buf = VALUE_CONTENTS_RAW (val);
|
||||
memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0);
|
||||
memset (buf, 0, TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
/* frame.base. */
|
||||
if (frame != NULL)
|
||||
ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf,
|
||||
@ -87,7 +87,7 @@ value_of_builtin_frame_fp_reg (struct frame_info *frame)
|
||||
struct value *val = allocate_value (builtin_type_void_data_ptr);
|
||||
char *buf = VALUE_CONTENTS_RAW (val);
|
||||
if (frame == NULL)
|
||||
memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0);
|
||||
memset (buf, 0, TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
else
|
||||
ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf,
|
||||
get_frame_base_address (frame));
|
||||
@ -105,7 +105,7 @@ value_of_builtin_frame_pc_reg (struct frame_info *frame)
|
||||
struct value *val = allocate_value (builtin_type_void_data_ptr);
|
||||
char *buf = VALUE_CONTENTS_RAW (val);
|
||||
if (frame == NULL)
|
||||
memset (buf, TYPE_LENGTH (VALUE_TYPE (val)), 0);
|
||||
memset (buf, 0, TYPE_LENGTH (VALUE_TYPE (val)));
|
||||
else
|
||||
ADDRESS_TO_POINTER (builtin_type_void_data_ptr, buf,
|
||||
get_frame_pc (frame));
|
||||
|
@ -40,6 +40,9 @@ __RCSID("$NetBSD: t_utimensat.c,v 1.5 2013/03/17 04:46:06 jmmv Exp $");
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/param.h>
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/stat.h>
|
||||
#endif
|
||||
#include <sys/time.h>
|
||||
|
||||
#define DIR "dir"
|
||||
|
@ -77,12 +77,12 @@ extern int SIZE_BUF;
|
||||
#ifdef __FreeBSD__
|
||||
#include <sys/capsicum.h>
|
||||
#include <sys/sysctl.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
#ifdef HAVE_CAPSICUM
|
||||
#include <libcapsicum.h>
|
||||
#include <libcapsicum_dns.h>
|
||||
#include <libcapsicum_service.h>
|
||||
#include <nv.h>
|
||||
#endif /* __FreeBSD__ */
|
||||
#ifdef HAVE_CAPSICUM
|
||||
#include <sys/capability.h>
|
||||
#include <sys/ioccom.h>
|
||||
#include <net/bpf.h>
|
||||
@ -966,8 +966,8 @@ main(int argc, char **argv)
|
||||
FILE *VFile;
|
||||
#ifdef HAVE_CAPSICUM
|
||||
cap_rights_t rights;
|
||||
int cansandbox;
|
||||
#endif /* HAVE_CAPSICUM */
|
||||
int cansandbox;
|
||||
|
||||
#ifdef WIN32
|
||||
if(wsockinit() != 0) return 1;
|
||||
|
@ -52,6 +52,8 @@
|
||||
..
|
||||
..
|
||||
etc
|
||||
rc.d
|
||||
..
|
||||
..
|
||||
games
|
||||
..
|
||||
|
@ -7,4 +7,6 @@ TESTSDIR= ${TESTSBASE}/etc
|
||||
.PATH: ${.CURDIR:H:H}/tests
|
||||
KYUAFILE= yes
|
||||
|
||||
TESTS_SUBDIRS+= rc.d
|
||||
|
||||
.include <bsd.test.mk>
|
||||
|
7
etc/tests/rc.d/Makefile
Normal file
7
etc/tests/rc.d/Makefile
Normal file
@ -0,0 +1,7 @@
|
||||
# $FreeBSD$
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/etc/rc.d
|
||||
|
||||
ATF_TESTS_SH+= routing_test
|
||||
|
||||
.include <bsd.test.mk>
|
138
etc/tests/rc.d/routing_test.sh
Executable file
138
etc/tests/rc.d/routing_test.sh
Executable file
@ -0,0 +1,138 @@
|
||||
#
|
||||
# Copyright (c) 2014 Spectra Logic 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,
|
||||
# without modification.
|
||||
# 2. Redistributions in binary form must reproduce at minimum a disclaimer
|
||||
# substantially similar to the "NO WARRANTY" disclaimer below
|
||||
# ("Disclaimer") and any redistribution must be conditioned upon
|
||||
# including a substantially similar Disclaimer requirement for further
|
||||
# binary redistribution.
|
||||
#
|
||||
# NO WARRANTY
|
||||
# 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 MERCHANTIBILITY AND FITNESS FOR
|
||||
# A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
|
||||
# HOLDERS OR CONTRIBUTORS BE LIABLE FOR 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 DAMAGES.
|
||||
#
|
||||
# Authors: Alan Somers (Spectra Logic Corporation)
|
||||
#
|
||||
# $FreeBSD$
|
||||
|
||||
atf_test_case static_ipv6_loopback_route_for_each_fib cleanup
|
||||
static_ipv6_loopback_route_for_each_fib_head()
|
||||
{
|
||||
atf_set "descr" "Every FIB should have a static IPv6 loopback route"
|
||||
atf_set "require.user" "root"
|
||||
atf_set "require.config" "fibs"
|
||||
atf_set "require.progs" "sysrc"
|
||||
}
|
||||
static_ipv6_loopback_route_for_each_fib_body()
|
||||
{
|
||||
# Configure the TAP interface to use an RFC5737 nonrouteable address
|
||||
# and a non-default fib
|
||||
ADDR="192.0.2.2"
|
||||
SUBNET="192.0.2.0"
|
||||
MASK="24"
|
||||
|
||||
# Check system configuration
|
||||
if [ 0 != `sysctl -n net.add_addr_allfibs` ]; then
|
||||
atf_skip "This test requires net.add_addr_allfibs=0"
|
||||
fi
|
||||
|
||||
get_fibs 1
|
||||
get_tap
|
||||
|
||||
# Configure a TAP interface in /etc/rc.conf. Register the sysrc
|
||||
# variable for cleanup.
|
||||
echo "ifconfig_${TAP}" >> "sysrc_vars_to_cleanup"
|
||||
sysrc ifconfig_${TAP}="${ADDR}/${MASK} fib ${FIB0}"
|
||||
|
||||
# Start the interface
|
||||
service netif start ${TAP}
|
||||
# Check for an IPv6 loopback route
|
||||
setfib ${FIB0} netstat -rn -f inet6 | grep -q "^::1.*lo0$"
|
||||
if [ 0 -eq $? ]; then
|
||||
atf_pass
|
||||
else
|
||||
setfib ${FIB0} netstat -rn -f inet6
|
||||
atf_fail "Did not find an IPv6 loopback route"
|
||||
fi
|
||||
}
|
||||
static_ipv6_loopback_route_for_each_fib_cleanup()
|
||||
{
|
||||
cleanup_sysrc
|
||||
cleanup_tap
|
||||
}
|
||||
|
||||
atf_init_test_cases()
|
||||
{
|
||||
atf_add_test_case static_ipv6_loopback_route_for_each_fib
|
||||
}
|
||||
|
||||
# Looks up one or more fibs from the configuration data and validates them.
|
||||
# Returns the results in the env varilables FIB0, FIB1, etc.
|
||||
# parameter numfibs The number of fibs to lookup
|
||||
get_fibs()
|
||||
{
|
||||
NUMFIBS=$1
|
||||
net_fibs=`sysctl -n net.fibs`
|
||||
i=0
|
||||
while [ $i -lt "$NUMFIBS" ]; do
|
||||
fib=`atf_config_get "fibs" | \
|
||||
awk -v i=$(( i + 1 )) '{print $i}'`
|
||||
echo "fib is ${fib}"
|
||||
eval FIB${i}=${fib}
|
||||
if [ "$fib" -ge "$net_fibs" ]; then
|
||||
msg="The ${i}th configured fib is ${fub}, which is "
|
||||
msg="$msg not less than net.fibs (${net_fibs})"
|
||||
atf_skip "$msg"
|
||||
fi
|
||||
i=$(( $i + 1 ))
|
||||
done
|
||||
}
|
||||
|
||||
|
||||
# Creates a new tap(4) interface, registers it for cleanup, and returns the
|
||||
# name via the environment variable TAP
|
||||
get_tap()
|
||||
{
|
||||
local TAPN=0
|
||||
while ! ifconfig tap${TAPN} create > /dev/null 2>&1; do
|
||||
if [ "$TAPN" -ge 8 ]; then
|
||||
atf_skip "Could not create a tap(4) interface"
|
||||
else
|
||||
TAPN=$(($TAPN + 1))
|
||||
fi
|
||||
done
|
||||
local TAPD=tap${TAPN}
|
||||
# Record the TAP device so we can clean it up later
|
||||
echo ${TAPD} >> "tap_devices_to_cleanup"
|
||||
TAP=${TAPD}
|
||||
}
|
||||
|
||||
cleanup_sysrc()
|
||||
{
|
||||
for var in `cat "sysrc_vars_to_cleanup"`; do
|
||||
sysrc -x $var
|
||||
done
|
||||
}
|
||||
|
||||
cleanup_tap()
|
||||
{
|
||||
for TAPD in `cat "tap_devices_to_cleanup"`; do
|
||||
ifconfig ${TAPD} destroy
|
||||
done
|
||||
}
|
@ -357,6 +357,10 @@ int __libc_system(const char *);
|
||||
int __libc_tcdrain(int);
|
||||
int __fcntl_compat(int fd, int cmd, ...);
|
||||
|
||||
int __sys_futimens(int fd, const struct timespec *times) __hidden;
|
||||
int __sys_utimensat(int fd, const char *path,
|
||||
const struct timespec *times, int flag) __hidden;
|
||||
|
||||
/* execve() with PATH processing to implement posix_spawnp() */
|
||||
int _execvpe(const char *, char * const *, char * const *);
|
||||
|
||||
|
@ -38,6 +38,10 @@ SRCS+= ${SYSCALL_COMPAT_SRCS}
|
||||
NOASM+= ${SYSCALL_COMPAT_SRCS:S/.c/.o/}
|
||||
.endif
|
||||
|
||||
SRCS+= futimens.c utimensat.c
|
||||
NOASM+= futimens.o utimensat.o
|
||||
PSEUDO+= _futimens.o _utimensat.o
|
||||
|
||||
INTERPOSED = \
|
||||
accept \
|
||||
accept4 \
|
||||
@ -310,6 +314,7 @@ MAN+= sctp_generic_recvmsg.2 \
|
||||
umask.2 \
|
||||
undelete.2 \
|
||||
unlink.2 \
|
||||
utimensat.2 \
|
||||
utimes.2 \
|
||||
utrace.2 \
|
||||
uuidgen.2 \
|
||||
@ -442,6 +447,7 @@ MLINKS+=timer_settime.2 timer_getoverrun.2 \
|
||||
timer_settime.2 timer_gettime.2
|
||||
MLINKS+=truncate.2 ftruncate.2
|
||||
MLINKS+=unlink.2 unlinkat.2
|
||||
MLINKS+=utimensat.2 futimens.2
|
||||
MLINKS+=utimes.2 futimes.2 \
|
||||
utimes.2 futimesat.2 \
|
||||
utimes.2 lutimes.2
|
||||
|
@ -397,7 +397,9 @@ FBSD_1.3 {
|
||||
};
|
||||
|
||||
FBSD_1.4 {
|
||||
futimens;
|
||||
ppoll;
|
||||
utimensat;
|
||||
};
|
||||
|
||||
FBSDprivate_1.0 {
|
||||
|
97
lib/libc/sys/futimens.c
Normal file
97
lib/libc/sys/futimens.c
Normal file
@ -0,0 +1,97 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Jilles Tjoelker
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
#include "libc_private.h"
|
||||
|
||||
int
|
||||
futimens(int fd, const struct timespec times[2])
|
||||
{
|
||||
struct timeval now, tv[2], *tvp;
|
||||
struct stat sb;
|
||||
|
||||
if (__getosreldate() >= 1100056)
|
||||
return (__sys_futimens(fd, times));
|
||||
|
||||
if (times == NULL || (times[0].tv_nsec == UTIME_NOW &&
|
||||
times[1].tv_nsec == UTIME_NOW))
|
||||
tvp = NULL;
|
||||
else if (times[0].tv_nsec == UTIME_OMIT &&
|
||||
times[1].tv_nsec == UTIME_OMIT)
|
||||
return (0);
|
||||
else {
|
||||
if ((times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) &&
|
||||
times[0].tv_nsec != UTIME_NOW &&
|
||||
times[0].tv_nsec != UTIME_OMIT) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if ((times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) &&
|
||||
times[1].tv_nsec != UTIME_NOW &&
|
||||
times[1].tv_nsec != UTIME_OMIT) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
tv[0].tv_sec = times[0].tv_sec;
|
||||
tv[0].tv_usec = times[0].tv_nsec / 1000;
|
||||
tv[1].tv_sec = times[1].tv_sec;
|
||||
tv[1].tv_usec = times[1].tv_nsec / 1000;
|
||||
tvp = tv;
|
||||
if (times[0].tv_nsec == UTIME_OMIT ||
|
||||
times[1].tv_nsec == UTIME_OMIT) {
|
||||
if (_fstat(fd, &sb) == -1)
|
||||
return (-1);
|
||||
if (times[0].tv_nsec == UTIME_OMIT) {
|
||||
tv[0].tv_sec = sb.st_atim.tv_sec;
|
||||
tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
|
||||
}
|
||||
if (times[1].tv_nsec == UTIME_OMIT) {
|
||||
tv[1].tv_sec = sb.st_mtim.tv_sec;
|
||||
tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
|
||||
}
|
||||
}
|
||||
if (times[0].tv_nsec == UTIME_NOW ||
|
||||
times[1].tv_nsec == UTIME_NOW) {
|
||||
if (gettimeofday(&now, NULL) == -1)
|
||||
return (-1);
|
||||
if (times[0].tv_nsec == UTIME_NOW)
|
||||
tv[0] = now;
|
||||
if (times[1].tv_nsec == UTIME_NOW)
|
||||
tv[1] = now;
|
||||
}
|
||||
}
|
||||
return (futimes(fd, tvp));
|
||||
}
|
292
lib/libc/sys/utimensat.2
Normal file
292
lib/libc/sys/utimensat.2
Normal file
@ -0,0 +1,292 @@
|
||||
.\" $NetBSD: utimes.2,v 1.13 1999/03/22 19:45:11 garbled Exp $
|
||||
.\"
|
||||
.\" Copyright (c) 1990, 1993
|
||||
.\" The Regents of the University of California. All rights reserved.
|
||||
.\" Copyright (c) 2012, Jilles Tjoelker
|
||||
.\"
|
||||
.\" 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.
|
||||
.\" 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.
|
||||
.\"
|
||||
.\" @(#)utimes.2 8.1 (Berkeley) 6/4/93
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd January 23, 2015
|
||||
.Dt UTIMENSAT 2
|
||||
.Os
|
||||
.Sh NAME
|
||||
.Nm futimens ,
|
||||
.Nm utimensat
|
||||
.Nd set file access and modification times
|
||||
.Sh LIBRARY
|
||||
.Lb libc
|
||||
.Sh SYNOPSIS
|
||||
.In sys/stat.h
|
||||
.Ft int
|
||||
.Fn futimens "int fd" "const struct timespec times[2]"
|
||||
.Ft int
|
||||
.Fo utimensat
|
||||
.Fa "int fd"
|
||||
.Fa "const char *path"
|
||||
.Fa "const struct timespec times[2]"
|
||||
.Fa "int flag"
|
||||
.Fc
|
||||
.Sh DESCRIPTION
|
||||
The access and modification times of the file named by
|
||||
.Fa path
|
||||
or referenced by
|
||||
.Fa fd
|
||||
are changed as specified by the argument
|
||||
.Fa times .
|
||||
The inode-change-time of the file is set to the current time.
|
||||
.Pp
|
||||
If
|
||||
.Fa path
|
||||
specifies a relative path,
|
||||
it is relative to the current working directory if
|
||||
.Fa fd
|
||||
is
|
||||
.Dv AT_FDCWD
|
||||
and otherwise relative to the directory associated with the file descriptor
|
||||
.Fa fd .
|
||||
.Pp
|
||||
The
|
||||
.Va tv_nsec
|
||||
field of a
|
||||
.Vt timespec
|
||||
structure
|
||||
can be set to the special value
|
||||
.Dv UTIME_NOW
|
||||
to set the current time, or to
|
||||
.Dv UTIME_OMIT
|
||||
to leave the time unchanged.
|
||||
In either case, the
|
||||
.Va tv_sec
|
||||
field is ignored.
|
||||
.Pp
|
||||
If
|
||||
.Fa times
|
||||
is
|
||||
.No non- Ns Dv NULL ,
|
||||
it is assumed to point to an array of two timespec structures.
|
||||
The access time is set to the value of the first element, and the
|
||||
modification time is set to the value of the second element.
|
||||
For file systems that support file birth (creation) times (such as
|
||||
.Dv UFS2 ) ,
|
||||
the birth time will be set to the value of the second element
|
||||
if the second element is older than the currently set birth time.
|
||||
To set both a birth time and a modification time,
|
||||
two calls are required; the first to set the birth time
|
||||
and the second to set the (presumably newer) modification time.
|
||||
Ideally a new system call will be added that allows the setting
|
||||
of all three times at once.
|
||||
If
|
||||
.Fa times
|
||||
is
|
||||
.Dv NULL ,
|
||||
this is equivalent to passing
|
||||
a pointer to an array of two timespec structures
|
||||
with both
|
||||
.Va tv_nsec
|
||||
fields set to
|
||||
.Dv UTIME_NOW .
|
||||
.Pp
|
||||
If both
|
||||
.Va tv_nsec
|
||||
fields are
|
||||
.Dv UTIME_OMIT ,
|
||||
the timestamps remain unchanged and
|
||||
no permissions are needed for the file itself,
|
||||
although search permissions may be required for the path prefix.
|
||||
The call may or may not succeed if the named file does not exist.
|
||||
.Pp
|
||||
If both
|
||||
.Va tv_nsec
|
||||
fields are
|
||||
.Dv UTIME_NOW ,
|
||||
the caller must be the owner of the file, have permission to
|
||||
write the file, or be the super-user.
|
||||
.Pp
|
||||
For all other values of the timestamps,
|
||||
the caller must be the owner of the file or be the super-user.
|
||||
.Pp
|
||||
The values for the
|
||||
.Fa flag
|
||||
argument of the
|
||||
.Fn utimensat
|
||||
system call
|
||||
are constructed by a bitwise-inclusive OR of flags from the following list,
|
||||
defined in
|
||||
.In fcntl.h :
|
||||
.Bl -tag -width indent
|
||||
.It Dv AT_SYMLINK_NOFOLLOW
|
||||
If
|
||||
.Fa path
|
||||
names a symbolic link, the symbolic link's times are changed.
|
||||
By default,
|
||||
.Fn utimensat
|
||||
changes the times of the file referenced by the symbolic link.
|
||||
.El
|
||||
.Sh RETURN VALUES
|
||||
.Rv -std
|
||||
.Sh COMPATIBILITY
|
||||
If the running kernel does not support this system call,
|
||||
a wrapper emulates it using
|
||||
.Xr fstatat 2 ,
|
||||
.Xr futimesat 2
|
||||
and
|
||||
.Xr lutimes 2 .
|
||||
As a result, timestamps will be rounded down to the nearest microsecond,
|
||||
.Dv UTIME_OMIT
|
||||
is not atomic and
|
||||
.Dv AT_SYMLINK_NOFOLLOW
|
||||
is not available with a path relative to a file descriptor.
|
||||
.Sh ERRORS
|
||||
These system calls will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EACCES
|
||||
The
|
||||
.Fa times
|
||||
argument is
|
||||
.Dv NULL ,
|
||||
or both
|
||||
.Va tv_nsec
|
||||
values are
|
||||
.Dv UTIME_NOW ,
|
||||
and the effective user ID of the process does not
|
||||
match the owner of the file, and is not the super-user, and write
|
||||
access is denied.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa times
|
||||
argument
|
||||
points outside the process's allocated address space.
|
||||
.It Bq Er EINVAL
|
||||
The
|
||||
.Va tv_usec
|
||||
component of at least one of the values specified by the
|
||||
.Fa times
|
||||
argument has a value less than 0 or greater than 999999.
|
||||
.It Bq Er EIO
|
||||
An I/O error occurred while reading or writing the affected inode.
|
||||
.It Bq Er EPERM
|
||||
The
|
||||
.Fa times
|
||||
argument is not
|
||||
.Dv NULL
|
||||
nor are both
|
||||
.Va tv_nsec
|
||||
values
|
||||
.Dv UTIME_NOW ,
|
||||
nor are both
|
||||
.Va tv_nsec
|
||||
values
|
||||
.Dv UTIME_OMIT
|
||||
and the calling process's effective user ID
|
||||
does not match the owner of the file and is not the super-user.
|
||||
.It Bq Er EPERM
|
||||
The named file has its immutable or append-only flag set, see the
|
||||
.Xr chflags 2
|
||||
manual page for more information.
|
||||
.It Bq Er EROFS
|
||||
The file system containing the file is mounted read-only.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn futimens
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa fd
|
||||
argument
|
||||
does not refer to a valid descriptor.
|
||||
.El
|
||||
.Pp
|
||||
The
|
||||
.Fn utimensat
|
||||
system call
|
||||
will fail if:
|
||||
.Bl -tag -width Er
|
||||
.It Bq Er EACCES
|
||||
Search permission is denied for a component of the path prefix.
|
||||
.It Bq Er EBADF
|
||||
The
|
||||
.Fa path
|
||||
argument does not specify an absolute path and the
|
||||
.Fa fd
|
||||
argument is neither
|
||||
.Dv AT_FDCWD
|
||||
nor a valid file descriptor.
|
||||
.It Bq Er EFAULT
|
||||
The
|
||||
.Fa path
|
||||
argument
|
||||
points outside the process's allocated address space.
|
||||
.It Bq Er ELOOP
|
||||
Too many symbolic links were encountered in translating the pathname.
|
||||
.It Bq Er ENAMETOOLONG
|
||||
A component of a pathname exceeded
|
||||
.Dv NAME_MAX
|
||||
characters, or an entire path name exceeded
|
||||
.Dv PATH_MAX
|
||||
characters.
|
||||
.It Bq Er ENOENT
|
||||
The named file does not exist.
|
||||
.It Bq Er ENOTDIR
|
||||
A component of the path prefix is not a directory.
|
||||
.It Bq Er ENOTDIR
|
||||
The
|
||||
.Fa path
|
||||
argument is not an absolute path and
|
||||
.Fa fd
|
||||
is neither
|
||||
.Dv AT_FDCWD
|
||||
nor a file descriptor associated with a directory.
|
||||
.It Bq Er ENOTSUP
|
||||
The running kernel does not support this system call and
|
||||
.Dv AT_SYMLINK_NOFOLLOW
|
||||
is used with a path relative to a file descriptor.
|
||||
.El
|
||||
.Sh SEE ALSO
|
||||
.Xr chflags 2 ,
|
||||
.Xr stat 2 ,
|
||||
.Xr symlink 2 ,
|
||||
.Xr utimes 2 ,
|
||||
.Xr utime 3 ,
|
||||
.Xr symlink 7
|
||||
.Sh STANDARDS
|
||||
The
|
||||
.Fn futimens
|
||||
and
|
||||
.Fn utimensat
|
||||
system calls are expected to conform to
|
||||
.St -p1003.1-2008 .
|
||||
.Sh HISTORY
|
||||
The
|
||||
.Fn futimens
|
||||
and
|
||||
.Fn utimensat
|
||||
system calls appeared in
|
||||
.Fx 11.0 .
|
109
lib/libc/sys/utimensat.c
Normal file
109
lib/libc/sys/utimensat.c
Normal file
@ -0,0 +1,109 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Jilles Tjoelker
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include "namespace.h"
|
||||
#include <sys/stat.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include "un-namespace.h"
|
||||
|
||||
#include "libc_private.h"
|
||||
|
||||
int
|
||||
utimensat(int fd, const char *path, const struct timespec times[2], int flag)
|
||||
{
|
||||
struct timeval now, tv[2], *tvp;
|
||||
struct stat sb;
|
||||
|
||||
if (__getosreldate() >= 1100056)
|
||||
return (__sys_utimensat(fd, path, times, flag));
|
||||
|
||||
if ((flag & ~AT_SYMLINK_NOFOLLOW) != 0) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if (times == NULL || (times[0].tv_nsec == UTIME_NOW &&
|
||||
times[1].tv_nsec == UTIME_NOW))
|
||||
tvp = NULL;
|
||||
else if (times[0].tv_nsec == UTIME_OMIT &&
|
||||
times[1].tv_nsec == UTIME_OMIT)
|
||||
return (0);
|
||||
else {
|
||||
if ((times[0].tv_nsec < 0 || times[0].tv_nsec > 999999999) &&
|
||||
times[0].tv_nsec != UTIME_NOW &&
|
||||
times[0].tv_nsec != UTIME_OMIT) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
if ((times[1].tv_nsec < 0 || times[1].tv_nsec > 999999999) &&
|
||||
times[1].tv_nsec != UTIME_NOW &&
|
||||
times[1].tv_nsec != UTIME_OMIT) {
|
||||
errno = EINVAL;
|
||||
return (-1);
|
||||
}
|
||||
tv[0].tv_sec = times[0].tv_sec;
|
||||
tv[0].tv_usec = times[0].tv_nsec / 1000;
|
||||
tv[1].tv_sec = times[1].tv_sec;
|
||||
tv[1].tv_usec = times[1].tv_nsec / 1000;
|
||||
tvp = tv;
|
||||
if (times[0].tv_nsec == UTIME_OMIT ||
|
||||
times[1].tv_nsec == UTIME_OMIT) {
|
||||
if (fstatat(fd, path, &sb, flag) == -1)
|
||||
return (-1);
|
||||
if (times[0].tv_nsec == UTIME_OMIT) {
|
||||
tv[0].tv_sec = sb.st_atim.tv_sec;
|
||||
tv[0].tv_usec = sb.st_atim.tv_nsec / 1000;
|
||||
}
|
||||
if (times[1].tv_nsec == UTIME_OMIT) {
|
||||
tv[1].tv_sec = sb.st_mtim.tv_sec;
|
||||
tv[1].tv_usec = sb.st_mtim.tv_nsec / 1000;
|
||||
}
|
||||
}
|
||||
if (times[0].tv_nsec == UTIME_NOW ||
|
||||
times[1].tv_nsec == UTIME_NOW) {
|
||||
if (gettimeofday(&now, NULL) == -1)
|
||||
return (-1);
|
||||
if (times[0].tv_nsec == UTIME_NOW)
|
||||
tv[0] = now;
|
||||
if (times[1].tv_nsec == UTIME_NOW)
|
||||
tv[1] = now;
|
||||
}
|
||||
}
|
||||
if ((flag & AT_SYMLINK_NOFOLLOW) == 0)
|
||||
return (futimesat(fd, path, tvp));
|
||||
else if ((flag & AT_SYMLINK_NOFOLLOW) != 0 &&
|
||||
(fd == AT_FDCWD || path[0] == '/'))
|
||||
return (lutimes(path, tvp));
|
||||
else {
|
||||
errno = ENOTSUP;
|
||||
return (-1);
|
||||
}
|
||||
}
|
@ -2,7 +2,7 @@
|
||||
|
||||
TESTSDIR= ${TESTSBASE}/lib/libc/c063
|
||||
|
||||
#TODO: t_o_search, t_utimensat
|
||||
#TODO: t_o_search
|
||||
|
||||
NETBSD_ATF_TESTS_C= faccessat
|
||||
NETBSD_ATF_TESTS_C+= fchmodat
|
||||
@ -18,6 +18,7 @@ NETBSD_ATF_TESTS_C+= readlinkat
|
||||
NETBSD_ATF_TESTS_C+= renameat
|
||||
NETBSD_ATF_TESTS_C+= symlinkat
|
||||
NETBSD_ATF_TESTS_C+= unlinkat
|
||||
NETBSD_ATF_TESTS_C+= utimensat
|
||||
|
||||
CFLAGS+= -D_INCOMPLETE_XOPEN_C063
|
||||
|
||||
|
@ -288,7 +288,7 @@ Thus
|
||||
printf(
|
||||
.Qq reg=%b\en ,
|
||||
3,
|
||||
.Qq \e10\e2BITTWO\e1BITONE\en
|
||||
.Qq \e10\e2BITTWO\e1BITONE
|
||||
);
|
||||
.Ed
|
||||
.Pp
|
||||
|
@ -187,7 +187,7 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
* the next characters (up to a control character, i.e. a character <= 32),
|
||||
* give the name of the register. Thus:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
|
||||
*
|
||||
* would produce output:
|
||||
*
|
||||
@ -500,7 +500,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
|
||||
while (percent < fmt)
|
||||
PCHAR(*percent++);
|
||||
/*
|
||||
* Since we ignore an formatting argument it is no
|
||||
* Since we ignore a formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
|
@ -279,6 +279,7 @@ ftp: packagesystem
|
||||
cp *.txz MANIFEST ftp
|
||||
|
||||
release: real-release vm-release cloudware-release
|
||||
@true
|
||||
|
||||
real-release:
|
||||
${MAKE} -C ${.CURDIR} ${.MAKEFLAGS} obj
|
||||
|
@ -50,8 +50,8 @@ vm-${_CW:tl}:
|
||||
|
||||
.if defined(WITH_VMIMAGES) && !empty(WITH_VMIMAGES)
|
||||
CLEANDIRS+= ${VMTARGETS}
|
||||
CLEANFILES+= ${VMBASE}.img
|
||||
. for FORMAT in ${VMFORMATS}
|
||||
CLEANFILES+= ${FORMAT}.img
|
||||
CLEANFILES+= ${VMBASE}.${FORMAT}
|
||||
. endfor
|
||||
.endif
|
||||
@ -65,7 +65,7 @@ vm-image:
|
||||
env TARGET=${TARGET} TARGET_ARCH=${TARGET_ARCH} \
|
||||
${.CURDIR}/scripts/mk-vmimage.sh \
|
||||
-C ${.CURDIR}/tools/vmimage.subr -d ${.OBJDIR}/${.TARGET} \
|
||||
-i ${.OBJDIR}/${VMBASE}.img -s ${VMSIZE} -f ${FORMAT} \
|
||||
-i ${.OBJDIR}/${FORMAT}.img -s ${VMSIZE} -f ${FORMAT} \
|
||||
-S ${WORLDDIR} -o ${.OBJDIR}/${VMBASE}.${FORMAT}
|
||||
. endfor
|
||||
.endif
|
||||
|
@ -20,7 +20,7 @@
|
||||
|
||||
<pubdate>$FreeBSD$</pubdate>
|
||||
|
||||
<!-- Last rev: 276551 -->
|
||||
<!-- Last rev: 277458 -->
|
||||
|
||||
<copyright>
|
||||
<year>2015</year>
|
||||
@ -691,6 +691,10 @@
|
||||
has been updated to support <acronym>UTF</acronym>-8, which
|
||||
additionally provides unicode support to &man.sh.1;.</para>
|
||||
|
||||
<para revision="277166" arch="powerpc">The &man.ptrace.2; system
|
||||
call has been updated include support for Altivec registers on
|
||||
&os;/&arch.powerpc;.</para>
|
||||
|
||||
<sect3 xml:id="abi-compat">
|
||||
<title><acronym>ABI</acronym> Compatibility</title>
|
||||
|
||||
@ -791,6 +795,11 @@
|
||||
<application>strings</application> were switched to the
|
||||
versions from the ELF Tool Chain project.</para>
|
||||
|
||||
<para revision="276881">The <literal>libedit</literal> library
|
||||
has been updated to include <acronym>UTF-8</acronym> support,
|
||||
adding <acronym>UTF-8</acronym> support to the &man.sh.1;
|
||||
shell.</para>
|
||||
|
||||
<para revision="277270"><application>OpenSSL</application> has
|
||||
been updated to version 1.0.1l.</para>
|
||||
</sect2>
|
||||
@ -804,7 +813,10 @@
|
||||
<sect2 xml:id="releng">
|
||||
<title>Release Engineering and Integration</title>
|
||||
|
||||
<para> </para>
|
||||
<para revision="277458" contrib="sponsor" sponsor="&ff;">The
|
||||
Release Engineering build tools have been updated to include
|
||||
support for producing virtual machine disk images for various
|
||||
cloud hosting providers.</para>
|
||||
</sect2>
|
||||
|
||||
<sect2 xml:id="doc">
|
||||
|
@ -734,8 +734,8 @@ populate_mfs_tree() {
|
||||
[ -n "${copy_files}" ] && do_copyfiles ${dst} copy_files
|
||||
do_copyfiles_user ${dst} || true
|
||||
[ -n "${links}" ] && do_links ${dst} links
|
||||
strip ${dst}/libexec/* ${dst}/lib/* ${dst}/stand/* 2> /dev/null || true
|
||||
|
||||
strip ${dst}/libexec/* ${dst}/lib/* 2> /dev/null || true
|
||||
# strip ${dst}/stand/* 2> /dev/null || true
|
||||
# The 'import_files' mechanism is deprecated, as it requires
|
||||
# root permissions to follow the symlinks, and also does
|
||||
# not let you rename the entries.
|
||||
@ -756,7 +756,7 @@ populate_mfs_tree() {
|
||||
# override the owner
|
||||
echo "/set uid=0 gid=0" > mtree.out
|
||||
mtree -ic -p ${dst} -k "" >> mtree.out
|
||||
log "mtre.out at ${BUILDDIR}/mtree.out"
|
||||
log "mtree.out at ${BUILDDIR}/mtree.out size ${MFS_SIZE}k"
|
||||
makefs -t ffs -o bsize=4096 -o fsize=512 \
|
||||
-s ${MFS_SIZE}k -f 1000 -F mtree.out ${c_fs} ${dst}
|
||||
ls -l ${c_fs} )
|
||||
|
@ -713,7 +713,7 @@ main(int argc, char *const *argv)
|
||||
ip->ip_hl = sizeof(struct ip) >> 2;
|
||||
ip->ip_tos = tos;
|
||||
ip->ip_id = 0;
|
||||
ip->ip_off = df ? IP_DF : 0;
|
||||
ip->ip_off = htons(df ? IP_DF : 0);
|
||||
ip->ip_ttl = ttl;
|
||||
ip->ip_p = IPPROTO_ICMP;
|
||||
ip->ip_src.s_addr = source ? sock_in.sin_addr.s_addr : INADDR_ANY;
|
||||
@ -1078,7 +1078,7 @@ pinger(void)
|
||||
if (options & F_HDRINCL) {
|
||||
cc += sizeof(struct ip);
|
||||
ip = (struct ip *)outpackhdr;
|
||||
ip->ip_len = cc;
|
||||
ip->ip_len = htons(cc);
|
||||
ip->ip_sum = in_cksum((u_short *)outpackhdr, cc);
|
||||
packet = outpackhdr;
|
||||
}
|
||||
|
@ -30,7 +30,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd November 10, 2013
|
||||
.Dd January 24, 2015
|
||||
.Dt TREE 3
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -53,8 +53,26 @@
|
||||
.Nm SPLAY_REMOVE ,
|
||||
.Nm RB_PROTOTYPE ,
|
||||
.Nm RB_PROTOTYPE_STATIC ,
|
||||
.Nm RB_PROTOTYPE_INSERT ,
|
||||
.Nm RB_PROTOTYPE_INSERT_COLOR ,
|
||||
.Nm RB_PROTOTYPE_REMOVE ,
|
||||
.Nm RB_PROTOTYPE_REMOVE_COLOR ,
|
||||
.Nm RB_PROTOTYPE_FIND ,
|
||||
.Nm RB_PROTOTYPE_NFIND ,
|
||||
.Nm RB_PROTOTYPE_NEXT ,
|
||||
.Nm RB_PROTOTYPE_PREV ,
|
||||
.Nm RB_PROTOTYPE_MINMAX ,
|
||||
.Nm RB_GENERATE ,
|
||||
.Nm RB_GENERATE_STATIC ,
|
||||
.Nm RB_GENERATE_INSERT ,
|
||||
.Nm RB_GENERATE_INSERT_COLOR ,
|
||||
.Nm RB_GENERATE_REMOVE ,
|
||||
.Nm RB_GENERATE_REMOVE_COLOR ,
|
||||
.Nm RB_GENERATE_FIND ,
|
||||
.Nm RB_GENERATE_NFIND ,
|
||||
.Nm RB_GENERATE_NEXT ,
|
||||
.Nm RB_GENERATE_PREV ,
|
||||
.Nm RB_GENERATE_MINMAX ,
|
||||
.Nm RB_ENTRY ,
|
||||
.Nm RB_HEAD ,
|
||||
.Nm RB_INITIALIZER ,
|
||||
@ -111,8 +129,26 @@
|
||||
.Fn SPLAY_REMOVE NAME "SPLAY_HEAD *head" "struct TYPE *elm"
|
||||
.Fn RB_PROTOTYPE NAME TYPE FIELD CMP
|
||||
.Fn RB_PROTOTYPE_STATIC NAME TYPE FIELD CMP
|
||||
.Fn RB_PROTOTYPE_INSERT NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_INSERT_COLOR NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_REMOVE NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_REMOVE_COLOR NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_FIND NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_NFIND NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_NEXT NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_PREV NAME TYPE ATTR
|
||||
.Fn RB_PROTOTYPE_MINMAX NAME TYPE ATTR
|
||||
.Fn RB_GENERATE NAME TYPE FIELD CMP
|
||||
.Fn RB_GENERATE_STATIC NAME TYPE FIELD CMP
|
||||
.Fn RB_GENERATE_INSERT NAME TYPE FIELD CMP ATTR
|
||||
.Fn RB_GENERATE_INSERT_COLOR NAME TYPE FIELD ATTR
|
||||
.Fn RB_GENERATE_REMOVE NAME TYPE FIELD ATTR
|
||||
.Fn RB_GENERATE_REMOVE_COLOR NAME TYPE FIELD ATTR
|
||||
.Fn RB_GENERATE_FIND NAME TYPE FIELD CMP ATTR
|
||||
.Fn RB_GENERATE_NFIND NAME TYPE FIELD CMP ATTR
|
||||
.Fn RB_GENERATE_NEXT NAME TYPE FIELD ATTR
|
||||
.Fn RB_GENERATE_PREV NAME TYPE FIELD ATTR
|
||||
.Fn RB_GENERATE_MINMAX NAME TYPE FIELD ATTR
|
||||
.Fn RB_ENTRY TYPE
|
||||
.Fn RB_HEAD HEADNAME TYPE
|
||||
.Fn RB_INITIALIZER "RB_HEAD *head"
|
||||
@ -377,6 +413,27 @@ The
|
||||
.Fa FIELD
|
||||
argument is the name of the element defined by
|
||||
.Fn RB_ENTRY .
|
||||
Individual prototypes can be declared with
|
||||
.Fn RB_PROTOTYPE_INSERT ,
|
||||
.Fn RB_PROTOTYPE_INSERT_COLOR ,
|
||||
.Fn RB_PROTOTYPE_REMOVE ,
|
||||
.Fn RB_PROTOTYPE_REMOVE_COLOR ,
|
||||
.Fn RB_PROTOTYPE_FIND ,
|
||||
.Fn RB_PROTOTYPE_NFIND ,
|
||||
.Fn RB_PROTOTYPE_NEXT ,
|
||||
.Fn RB_PROTOTYPE_PREV ,
|
||||
and
|
||||
.Fn RB_PROTOTYPE_MINMAX
|
||||
in case not all functions are required. The individual prototype macros expect
|
||||
.Fa NAME ,
|
||||
.Fa TYPE ,
|
||||
and
|
||||
.Fa ATTR
|
||||
arguments. The
|
||||
.Fa ATTR
|
||||
argument must be empty for global functions or
|
||||
.Fa static
|
||||
for static functions.
|
||||
.Pp
|
||||
The function bodies are generated with the
|
||||
.Fn RB_GENERATE
|
||||
@ -388,6 +445,18 @@ These macros take the same arguments as the
|
||||
and
|
||||
.Fn RB_PROTOTYPE_STATIC
|
||||
macros, but should be used only once.
|
||||
As an alternative individual function bodies are generated with the
|
||||
.Fn RB_GENERATE_INSERT ,
|
||||
.Fn RB_GENERATE_INSERT_COLOR ,
|
||||
.Fn RB_GENERATE_REMOVE ,
|
||||
.Fn RB_GENERATE_REMOVE_COLOR ,
|
||||
.Fn RB_GENERATE_FIND ,
|
||||
.Fn RB_GENERATE_NFIND ,
|
||||
.Fn RB_GENERATE_NEXT ,
|
||||
.Fn RB_GENERATE_PREV ,
|
||||
and
|
||||
.Fn RB_GENERATE_MINMAX
|
||||
macros.
|
||||
.Pp
|
||||
Finally,
|
||||
the
|
||||
|
@ -32,7 +32,7 @@
|
||||
.\"
|
||||
.\" $FreeBSD$
|
||||
.\"
|
||||
.Dd September 23, 2013
|
||||
.Dd January 23, 2015
|
||||
.Dt RIGHTS 4
|
||||
.Os
|
||||
.Sh NAME
|
||||
@ -272,9 +272,13 @@ with the
|
||||
flag.
|
||||
.It Dv CAP_FUTIMES
|
||||
Permit
|
||||
.Xr futimes 2
|
||||
.Xr futimens 2
|
||||
and
|
||||
.Xr futimes 2 ,
|
||||
and permit
|
||||
.Xr futimesat 2
|
||||
and
|
||||
.Xr utimensat 2
|
||||
if the
|
||||
.Dv CAP_LOOKUP
|
||||
right is also present.
|
||||
|
@ -151,7 +151,7 @@ void
|
||||
printf_test(void)
|
||||
{
|
||||
|
||||
printf("reg=%b\en", 3, "\e10\e2BITTWO\e1BITONE\en");
|
||||
printf("reg=%b\en", 3, "\e10\e2BITTWO\e1BITONE");
|
||||
printf("out: %4D\en", "AAAA", ":");
|
||||
}
|
||||
.Ed
|
||||
|
@ -80,6 +80,7 @@ SYSCTL_NODE(_hw_vmm, OID_AUTO, svm, CTLFLAG_RW, NULL, NULL);
|
||||
#define AMD_CPUID_SVM_DECODE_ASSIST BIT(7) /* Decode assist */
|
||||
#define AMD_CPUID_SVM_PAUSE_INC BIT(10) /* Pause intercept filter. */
|
||||
#define AMD_CPUID_SVM_PAUSE_FTH BIT(12) /* Pause filter threshold */
|
||||
#define AMD_CPUID_SVM_AVIC BIT(13) /* AVIC present */
|
||||
|
||||
#define VMCB_CACHE_DEFAULT (VMCB_CACHE_ASID | \
|
||||
VMCB_CACHE_IOPM | \
|
||||
|
@ -82,8 +82,6 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
|
||||
int error = 0;
|
||||
vm_offset_t addr, eaddr;
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
while (uio->uio_resid > 0 && error == 0) {
|
||||
iov = uio->uio_iov;
|
||||
if (iov->iov_len == 0) {
|
||||
|
@ -28,6 +28,9 @@ arm/freescale/imx/imx_machdep.c standard
|
||||
arm/freescale/imx/imx_gpt.c standard
|
||||
arm/freescale/imx/imx_gpio.c optional gpio
|
||||
arm/freescale/imx/imx_i2c.c optional fsliic
|
||||
arm/freescale/imx/imx6_sdma.c optional sdma
|
||||
arm/freescale/imx/imx6_audmux.c optional sound
|
||||
arm/freescale/imx/imx6_ssi.c optional sound
|
||||
|
||||
#
|
||||
# Optional devices.
|
||||
@ -52,3 +55,19 @@ arm/freescale/imx/imx6_usbphy.c optional ehci
|
||||
# Not ready yet...
|
||||
#
|
||||
#arm/freescale/imx/imx51_ipuv3.c optional sc
|
||||
|
||||
# SDMA firmware
|
||||
sdma_fw.c optional sdma_fw \
|
||||
compile-with "${AWK} -f $S/tools/fw_stub.awk sdma-imx6q-to1.bin:sdma_fw -msdma -c${.TARGET}" \
|
||||
no-implicit-rule before-depend local \
|
||||
clean "sdma_fw.c"
|
||||
sdma-imx6q-to1.fwo optional sdma_fw \
|
||||
dependency "sdma-imx6q-to1.bin" \
|
||||
compile-with "${LD} -b binary -d -warn-common -r -d -o ${.TARGET} sdma-imx6q-to1.bin" \
|
||||
no-implicit-rule \
|
||||
clean "sdma-imx6q-to1.fwo"
|
||||
sdma-imx6q-to1.bin optional sdma_fw \
|
||||
dependency "$S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \
|
||||
compile-with "uudecode < $S/contrib/dev/imx/sdma-imx6q-to1.bin.uu" \
|
||||
no-obj no-implicit-rule \
|
||||
clean "sdma-imx6q-to1.bin"
|
||||
|
@ -710,6 +710,27 @@ imx6_anatop_attach(device_t dev)
|
||||
return (err);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd)
|
||||
{
|
||||
int reg;
|
||||
|
||||
/*
|
||||
* Audio PLL (PLL4).
|
||||
* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM)
|
||||
*/
|
||||
|
||||
reg = (IMX6_ANALOG_CCM_PLL_AUDIO_ENABLE);
|
||||
reg &= ~(IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_MASK << \
|
||||
IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT);
|
||||
reg |= (mfi << IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT);
|
||||
imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO, reg);
|
||||
imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO_NUM, mfn);
|
||||
imx6_anatop_write_4(IMX6_ANALOG_CCM_PLL_AUDIO_DENOM, mfd);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
imx6_anatop_probe(device_t dev)
|
||||
{
|
||||
|
@ -58,6 +58,9 @@
|
||||
#define IMX6_ANALOG_CCM_PLL_SYS_NUM 0x050
|
||||
#define IMX6_ANALOG_CCM_PLL_SYS_DENOM 0x060
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO 0x070
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_ENABLE (1 << 13)
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_SHIFT 0
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_DIV_SELECT_MASK 0x7f
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_SET 0x074
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_CLR 0x078
|
||||
#define IMX6_ANALOG_CCM_PLL_AUDIO_TOG 0x07C
|
||||
|
@ -42,4 +42,6 @@ void imx6_anatop_write_4(bus_size_t _offset, uint32_t _value);
|
||||
|
||||
uint32_t imx6_get_cpu_clock(void);
|
||||
|
||||
uint32_t pll4_configure_output(uint32_t mfi, uint32_t mfn, uint32_t mfd);
|
||||
|
||||
#endif
|
||||
|
159
sys/arm/freescale/imx/imx6_audmux.c
Normal file
159
sys/arm/freescale/imx/imx6_audmux.c
Normal file
@ -0,0 +1,159 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i.MX6 Digital Audio Multiplexer (AUDMUX)
|
||||
* Chapter 16, i.MX 6Dual/6Quad Applications Processor Reference Manual,
|
||||
* Rev. 1, 04/2013
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_space_read_4(_sc->bst, _sc->bsh, _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
|
||||
|
||||
#define AUDMUX_PTCR(n) (0x8 * (n - 1)) /* Port Timing Control Register */
|
||||
#define PTCR_TFS_DIR (1 << 31) /* Transmit Frame Sync Direction Control */
|
||||
#define PTCR_TFSEL_S 27 /* Transmit Frame Sync Select */
|
||||
#define PTCR_TFSEL_M 0xf
|
||||
#define PTCR_TCLKDIR (1 << 26) /* Transmit Clock Direction Control */
|
||||
#define PTCR_TCSEL_S 22 /* Transmit Clock Select. */
|
||||
#define PTCR_TCSEL_M 0xf
|
||||
#define PTCR_RFS_DIR (1 << 21) /* Receive Frame Sync Direction Control */
|
||||
#define PTCR_SYN (1 << 11)
|
||||
#define AUDMUX_PDCR(n) (0x8 * (n - 1) + 0x4) /* Port Data Control Reg */
|
||||
#define PDCR_RXDSEL_S 13 /* Receive Data Select */
|
||||
#define PDCR_RXDSEL_M 0x3
|
||||
#define PDCR_RXDSEL_PORT(n) (n - 1)
|
||||
|
||||
struct audmux_softc {
|
||||
struct resource *res[1];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
void *ih;
|
||||
};
|
||||
|
||||
static struct resource_spec audmux_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int
|
||||
audmux_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "fsl,imx6q-audmux"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "i.MX6 Digital Audio Multiplexer");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static int
|
||||
audmux_configure(struct audmux_softc *sc,
|
||||
int ssi_port, int audmux_port)
|
||||
{
|
||||
uint32_t reg;
|
||||
|
||||
/* Direction: output */
|
||||
reg = (PTCR_TFS_DIR | PTCR_TCLKDIR | PTCR_SYN);
|
||||
WRITE4(sc, AUDMUX_PTCR(audmux_port), reg);
|
||||
|
||||
/* Select source */
|
||||
reg = (PDCR_RXDSEL_PORT(ssi_port) << PDCR_RXDSEL_S);
|
||||
WRITE4(sc, AUDMUX_PDCR(audmux_port), reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
audmux_attach(device_t dev)
|
||||
{
|
||||
struct audmux_softc *sc;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
|
||||
if (bus_alloc_resources(dev, audmux_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
/*
|
||||
* Direct SSI1 output to AUDMUX5 pins.
|
||||
* TODO: dehardcore this.
|
||||
*/
|
||||
audmux_configure(sc, 1, 5);
|
||||
|
||||
return (0);
|
||||
};
|
||||
|
||||
static device_method_t audmux_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, audmux_probe),
|
||||
DEVMETHOD(device_attach, audmux_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t audmux_driver = {
|
||||
"audmux",
|
||||
audmux_methods,
|
||||
sizeof(struct audmux_softc),
|
||||
};
|
||||
|
||||
static devclass_t audmux_devclass;
|
||||
|
||||
DRIVER_MODULE(audmux, simplebus, audmux_driver, audmux_devclass, 0, 0);
|
@ -94,7 +94,7 @@ ccm_init_gates(struct ccm_softc *sc)
|
||||
WR4(sc, CCM_CCGR2, 0x0fffffc0); /* ipmux & ipsync (bridges), iomux, i2c */
|
||||
WR4(sc, CCM_CCGR3, 0x3ff00000); /* DDR memory controller */
|
||||
WR4(sc, CCM_CCGR4, 0x0000f300); /* pl301 bus crossbar */
|
||||
WR4(sc, CCM_CCGR5, 0x0f000000); /* uarts */
|
||||
WR4(sc, CCM_CCGR5, 0x0ffc00c0); /* uarts, ssi, sdma */
|
||||
WR4(sc, CCM_CCGR6, 0x000000ff); /* usdhc 1-4 */
|
||||
}
|
||||
|
||||
@ -179,6 +179,58 @@ ccm_probe(device_t dev)
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
void
|
||||
imx_ccm_ssi_configure(device_t _ssidev)
|
||||
{
|
||||
struct ccm_softc *sc;
|
||||
uint32_t reg;
|
||||
|
||||
sc = ccm_sc;
|
||||
|
||||
/*
|
||||
* Select PLL4 (Audio PLL) clock multiplexer as source.
|
||||
* PLL output frequency = Fref * (DIV_SELECT + NUM/DENOM).
|
||||
*/
|
||||
|
||||
reg = RD4(sc, CCM_CSCMR1);
|
||||
reg &= ~(SSI_CLK_SEL_M << SSI1_CLK_SEL_S);
|
||||
reg |= (SSI_CLK_SEL_PLL4 << SSI1_CLK_SEL_S);
|
||||
reg &= ~(SSI_CLK_SEL_M << SSI2_CLK_SEL_S);
|
||||
reg |= (SSI_CLK_SEL_PLL4 << SSI2_CLK_SEL_S);
|
||||
reg &= ~(SSI_CLK_SEL_M << SSI3_CLK_SEL_S);
|
||||
reg |= (SSI_CLK_SEL_PLL4 << SSI3_CLK_SEL_S);
|
||||
WR4(sc, CCM_CSCMR1, reg);
|
||||
|
||||
/*
|
||||
* Ensure we have set hardware-default values
|
||||
* for pre and post dividers.
|
||||
*/
|
||||
|
||||
/* SSI1 and SSI3 */
|
||||
reg = RD4(sc, CCM_CS1CDR);
|
||||
/* Divide by 2 */
|
||||
reg &= ~(SSI_CLK_PODF_MASK << SSI1_CLK_PODF_SHIFT);
|
||||
reg &= ~(SSI_CLK_PODF_MASK << SSI3_CLK_PODF_SHIFT);
|
||||
reg |= (0x1 << SSI1_CLK_PODF_SHIFT);
|
||||
reg |= (0x1 << SSI3_CLK_PODF_SHIFT);
|
||||
/* Divide by 4 */
|
||||
reg &= ~(SSI_CLK_PRED_MASK << SSI1_CLK_PRED_SHIFT);
|
||||
reg &= ~(SSI_CLK_PRED_MASK << SSI3_CLK_PRED_SHIFT);
|
||||
reg |= (0x3 << SSI1_CLK_PRED_SHIFT);
|
||||
reg |= (0x3 << SSI3_CLK_PRED_SHIFT);
|
||||
WR4(sc, CCM_CS1CDR, reg);
|
||||
|
||||
/* SSI2 */
|
||||
reg = RD4(sc, CCM_CS2CDR);
|
||||
/* Divide by 2 */
|
||||
reg &= ~(SSI_CLK_PODF_MASK << SSI2_CLK_PODF_SHIFT);
|
||||
reg |= (0x1 << SSI2_CLK_PODF_SHIFT);
|
||||
/* Divide by 4 */
|
||||
reg &= ~(SSI_CLK_PRED_MASK << SSI2_CLK_PRED_SHIFT);
|
||||
reg |= (0x3 << SSI2_CLK_PRED_SHIFT);
|
||||
WR4(sc, CCM_CS2CDR, reg);
|
||||
}
|
||||
|
||||
void
|
||||
imx_ccm_usb_enable(device_t _usbdev)
|
||||
{
|
||||
|
@ -29,6 +29,26 @@
|
||||
#ifndef IMX6_CCMREG_H
|
||||
#define IMX6_CCMREG_H
|
||||
|
||||
#define CCM_CSCMR1 0x01C
|
||||
#define SSI1_CLK_SEL_S 10
|
||||
#define SSI2_CLK_SEL_S 12
|
||||
#define SSI3_CLK_SEL_S 14
|
||||
#define SSI_CLK_SEL_M 0x3
|
||||
#define SSI_CLK_SEL_508_PFD 0
|
||||
#define SSI_CLK_SEL_454_PFD 1
|
||||
#define SSI_CLK_SEL_PLL4 2
|
||||
#define CCM_CSCMR2 0x020
|
||||
#define CCM_CS1CDR 0x028
|
||||
#define SSI1_CLK_PODF_SHIFT 0
|
||||
#define SSI1_CLK_PRED_SHIFT 6
|
||||
#define SSI3_CLK_PODF_SHIFT 16
|
||||
#define SSI3_CLK_PRED_SHIFT 22
|
||||
#define SSI_CLK_PODF_MASK 0x3f
|
||||
#define SSI_CLK_PRED_MASK 0x7
|
||||
#define CCM_CS2CDR 0x02C
|
||||
#define SSI2_CLK_PODF_SHIFT 0
|
||||
#define SSI2_CLK_PRED_SHIFT 6
|
||||
#define CCM_CSCDR2 0x038
|
||||
#define CCM_CLPCR 0x054
|
||||
#define CCM_CLPCR_LPM_MASK 0x03
|
||||
#define CCM_CLPCR_LPM_RUN 0x00
|
||||
|
518
sys/arm/freescale/imx/imx6_sdma.c
Normal file
518
sys/arm/freescale/imx/imx6_sdma.c
Normal file
@ -0,0 +1,518 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i.MX6 Smart Direct Memory Access Controller (sDMA)
|
||||
* Chapter 41, i.MX 6Dual/6Quad Applications Processor Reference Manual,
|
||||
* Rev. 1, 04/2013
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/endian.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
#include <sys/firmware.h>
|
||||
|
||||
#include <vm/vm.h>
|
||||
#include <vm/vm_extern.h>
|
||||
#include <vm/vm_kern.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <arm/freescale/imx/imx6_sdma.h>
|
||||
|
||||
#define MAX_BD (PAGE_SIZE / sizeof(struct sdma_buffer_descriptor))
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_space_read_4(_sc->bst, _sc->bsh, _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
|
||||
|
||||
struct sdma_softc *sdma_sc;
|
||||
|
||||
static struct resource_spec sdma_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static void
|
||||
sdma_intr(void *arg)
|
||||
{
|
||||
struct sdma_buffer_descriptor *bd;
|
||||
struct sdma_channel *channel;
|
||||
struct sdma_conf *conf;
|
||||
struct sdma_softc *sc;
|
||||
int pending;
|
||||
int i;
|
||||
int j;
|
||||
|
||||
sc = arg;
|
||||
|
||||
pending = READ4(sc, SDMAARM_INTR);
|
||||
|
||||
/* Ack intr */
|
||||
WRITE4(sc, SDMAARM_INTR, pending);
|
||||
|
||||
for (i = 0; i < SDMA_N_CHANNELS; i++) {
|
||||
if ((pending & (1 << i)) == 0)
|
||||
continue;
|
||||
channel = &sc->channel[i];
|
||||
conf = channel->conf;
|
||||
if (!conf)
|
||||
continue;
|
||||
for (j = 0; j < conf->num_bd; j++) {
|
||||
bd = &channel->bd[j];
|
||||
bd->mode.status |= BD_DONE;
|
||||
if (bd->mode.status & BD_RROR)
|
||||
printf("sDMA error\n");
|
||||
}
|
||||
|
||||
conf->ih(conf->ih_user, 1);
|
||||
|
||||
WRITE4(sc, SDMAARM_HSTART, (1 << i));
|
||||
}
|
||||
}
|
||||
|
||||
static int
|
||||
sdma_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "fsl,imx6q-sdma"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "i.MX6 Smart Direct Memory Access Controller");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
int
|
||||
sdma_start(int chn)
|
||||
{
|
||||
struct sdma_softc *sc;
|
||||
|
||||
sc = sdma_sc;
|
||||
|
||||
WRITE4(sc, SDMAARM_HSTART, (1 << chn));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sdma_stop(int chn)
|
||||
{
|
||||
struct sdma_softc *sc;
|
||||
|
||||
sc = sdma_sc;
|
||||
|
||||
WRITE4(sc, SDMAARM_STOP_STAT, (1 << chn));
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sdma_alloc(void)
|
||||
{
|
||||
struct sdma_channel *channel;
|
||||
struct sdma_softc *sc;
|
||||
int found;
|
||||
int chn;
|
||||
int i;
|
||||
|
||||
sc = sdma_sc;
|
||||
found = 0;
|
||||
|
||||
/* Channel 0 can't be used */
|
||||
for (i = 1; i < SDMA_N_CHANNELS; i++) {
|
||||
channel = &sc->channel[i];
|
||||
if (channel->in_use == 0) {
|
||||
channel->in_use = 1;
|
||||
found = 1;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
return (-1);
|
||||
|
||||
chn = i;
|
||||
|
||||
/* Allocate area for buffer descriptors */
|
||||
channel->bd = (void *)kmem_alloc_contig(kernel_arena,
|
||||
PAGE_SIZE, M_ZERO, 0, ~0, PAGE_SIZE, 0,
|
||||
VM_MEMATTR_UNCACHEABLE);
|
||||
|
||||
return (chn);
|
||||
}
|
||||
|
||||
int
|
||||
sdma_free(int chn)
|
||||
{
|
||||
struct sdma_channel *channel;
|
||||
struct sdma_softc *sc;
|
||||
|
||||
sc = sdma_sc;
|
||||
|
||||
channel = &sc->channel[chn];
|
||||
channel->in_use = 0;
|
||||
|
||||
kmem_free(kernel_arena, (vm_offset_t)channel->bd,
|
||||
PAGE_SIZE);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sdma_overrides(struct sdma_softc *sc, int chn,
|
||||
int evt, int host, int dsp)
|
||||
{
|
||||
int reg;
|
||||
|
||||
/* Ignore sDMA requests */
|
||||
reg = READ4(sc, SDMAARM_EVTOVR);
|
||||
if (evt)
|
||||
reg |= (1 << chn);
|
||||
else
|
||||
reg &= ~(1 << chn);
|
||||
WRITE4(sc, SDMAARM_EVTOVR, reg);
|
||||
|
||||
/* Ignore enable bit (HE) */
|
||||
reg = READ4(sc, SDMAARM_HOSTOVR);
|
||||
if (host)
|
||||
reg |= (1 << chn);
|
||||
else
|
||||
reg &= ~(1 << chn);
|
||||
WRITE4(sc, SDMAARM_HOSTOVR, reg);
|
||||
|
||||
/* Prevent sDMA channel from starting */
|
||||
reg = READ4(sc, SDMAARM_DSPOVR);
|
||||
if (!dsp)
|
||||
reg |= (1 << chn);
|
||||
else
|
||||
reg &= ~(1 << chn);
|
||||
WRITE4(sc, SDMAARM_DSPOVR, reg);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
int
|
||||
sdma_configure(int chn, struct sdma_conf *conf)
|
||||
{
|
||||
struct sdma_buffer_descriptor *bd0;
|
||||
struct sdma_buffer_descriptor *bd;
|
||||
struct sdma_context_data *context;
|
||||
struct sdma_channel *channel;
|
||||
struct sdma_softc *sc;
|
||||
#if 0
|
||||
int timeout;
|
||||
int ret;
|
||||
#endif
|
||||
int i;
|
||||
|
||||
sc = sdma_sc;
|
||||
|
||||
channel = &sc->channel[chn];
|
||||
channel->conf = conf;
|
||||
|
||||
/* Ensure operation has stopped */
|
||||
sdma_stop(chn);
|
||||
|
||||
/* Set priority and enable the channel */
|
||||
WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
|
||||
WRITE4(sc, SDMAARM_CHNENBL(conf->event), (1 << chn));
|
||||
|
||||
sdma_overrides(sc, chn, 0, 0, 0);
|
||||
|
||||
if (conf->num_bd > MAX_BD) {
|
||||
device_printf(sc->dev, "Error: too much buffer"
|
||||
" descriptors requested\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
for (i = 0; i < conf->num_bd; i++) {
|
||||
bd = &channel->bd[i];
|
||||
bd->mode.command = conf->command;
|
||||
bd->mode.status = BD_DONE | BD_EXTD | BD_CONT | BD_INTR;
|
||||
if (i == (conf->num_bd - 1))
|
||||
bd->mode.status |= BD_WRAP;
|
||||
bd->mode.count = conf->period;
|
||||
bd->buffer_addr = conf->saddr + (conf->period * i);
|
||||
bd->ext_buffer_addr = 0;
|
||||
}
|
||||
|
||||
sc->ccb[chn].base_bd_ptr = vtophys(channel->bd);
|
||||
sc->ccb[chn].current_bd_ptr = vtophys(channel->bd);
|
||||
|
||||
/*
|
||||
* Load context.
|
||||
*
|
||||
* i.MX6 Reference Manual: Appendix A SDMA Scripts
|
||||
* A.3.1.7.1 (mcu_2_app)
|
||||
*/
|
||||
|
||||
/*
|
||||
* TODO: allow using other scripts
|
||||
*/
|
||||
context = sc->context;
|
||||
memset(context, 0, sizeof(*context));
|
||||
context->channel_state.pc = sc->fw_scripts->mcu_2_app_addr;
|
||||
|
||||
/*
|
||||
* Tx FIFO 0 address (r6)
|
||||
* Event_mask (r1)
|
||||
* Event2_mask (r0)
|
||||
* Watermark level (r7)
|
||||
*/
|
||||
|
||||
if (conf->event > 32) {
|
||||
context->gReg[0] = (1 << (conf->event % 32));
|
||||
context->gReg[1] = 0;
|
||||
} else {
|
||||
context->gReg[0] = 0;
|
||||
context->gReg[1] = (1 << conf->event);
|
||||
}
|
||||
|
||||
context->gReg[6] = conf->daddr;
|
||||
context->gReg[7] = conf->word_length;
|
||||
|
||||
bd0 = sc->bd0;
|
||||
bd0->mode.command = C0_SETDM;
|
||||
bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
|
||||
bd0->mode.count = sizeof(*context) / 4;
|
||||
bd0->buffer_addr = sc->context_phys;
|
||||
bd0->ext_buffer_addr = 2048 + (sizeof(*context) / 4) * chn;
|
||||
|
||||
WRITE4(sc, SDMAARM_HSTART, 1);
|
||||
|
||||
#if 0
|
||||
/* Debug purposes */
|
||||
|
||||
timeout = 1000;
|
||||
while (!(ret = READ4(sc, SDMAARM_INTR) & 1)) {
|
||||
if (timeout-- <= 0)
|
||||
break;
|
||||
DELAY(10);
|
||||
};
|
||||
|
||||
if (!ret) {
|
||||
device_printf(sc->dev, "Failed to load context.\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
WRITE4(sc, SDMAARM_INTR, ret);
|
||||
|
||||
device_printf(sc->dev, "Context loaded successfully.\n");
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
load_firmware(struct sdma_softc *sc)
|
||||
{
|
||||
struct sdma_firmware_header *header;
|
||||
const struct firmware *fp;
|
||||
|
||||
fp = firmware_get("sdma_fw");
|
||||
if (fp == NULL) {
|
||||
device_printf(sc->dev, "Can't get firmware.\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
header = (struct sdma_firmware_header *)fp->data;
|
||||
if (header->magic != FW_HEADER_MAGIC) {
|
||||
device_printf(sc->dev, "Can't use firmware.\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
sc->fw_header = header;
|
||||
sc->fw_scripts = (void *)((char *)header +
|
||||
header->script_addrs_start);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
boot_firmware(struct sdma_softc *sc)
|
||||
{
|
||||
struct sdma_buffer_descriptor *bd0;
|
||||
uint32_t *ram_code;
|
||||
int timeout;
|
||||
int ret;
|
||||
int chn;
|
||||
int sz;
|
||||
int i;
|
||||
|
||||
ram_code = (void *)((char *)sc->fw_header +
|
||||
sc->fw_header->ram_code_start);
|
||||
|
||||
/* Make sure SDMA has not started yet */
|
||||
WRITE4(sc, SDMAARM_MC0PTR, 0);
|
||||
|
||||
sz = SDMA_N_CHANNELS * sizeof(struct sdma_channel_control) + \
|
||||
sizeof(struct sdma_context_data);
|
||||
sc->ccb = (void *)kmem_alloc_contig(kernel_arena,
|
||||
sz, M_ZERO, 0, ~0, PAGE_SIZE, 0, VM_MEMATTR_UNCACHEABLE);
|
||||
sc->ccb_phys = vtophys(sc->ccb);
|
||||
|
||||
sc->context = (void *)((char *)sc->ccb + \
|
||||
SDMA_N_CHANNELS * sizeof(struct sdma_channel_control));
|
||||
sc->context_phys = vtophys(sc->context);
|
||||
|
||||
/* Disable all the channels */
|
||||
for (i = 0; i < SDMA_N_EVENTS; i++)
|
||||
WRITE4(sc, SDMAARM_CHNENBL(i), 0);
|
||||
|
||||
/* All channels have priority 0 */
|
||||
for (i = 0; i < SDMA_N_CHANNELS; i++)
|
||||
WRITE4(sc, SDMAARM_SDMA_CHNPRI(i), 0);
|
||||
|
||||
/* Channel 0 is used for booting firmware */
|
||||
chn = 0;
|
||||
|
||||
sc->bd0 = (void *)kmem_alloc_contig(kernel_arena,
|
||||
PAGE_SIZE, M_ZERO, 0, ~0, PAGE_SIZE, 0,
|
||||
VM_MEMATTR_UNCACHEABLE);
|
||||
bd0 = sc->bd0;
|
||||
sc->ccb[chn].base_bd_ptr = vtophys(bd0);
|
||||
sc->ccb[chn].current_bd_ptr = vtophys(bd0);
|
||||
|
||||
WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
|
||||
|
||||
sdma_overrides(sc, chn, 1, 0, 0);
|
||||
|
||||
/* XXX: not sure what is that */
|
||||
WRITE4(sc, SDMAARM_CHN0ADDR, 0x4050);
|
||||
|
||||
WRITE4(sc, SDMAARM_CONFIG, 0);
|
||||
WRITE4(sc, SDMAARM_MC0PTR, sc->ccb_phys);
|
||||
WRITE4(sc, SDMAARM_CONFIG, CONFIG_CSM);
|
||||
WRITE4(sc, SDMAARM_SDMA_CHNPRI(chn), 1);
|
||||
|
||||
bd0->mode.command = C0_SETPM;
|
||||
bd0->mode.status = BD_DONE | BD_INTR | BD_WRAP | BD_EXTD;
|
||||
bd0->mode.count = sc->fw_header->ram_code_size / 2;
|
||||
bd0->buffer_addr = vtophys(ram_code);
|
||||
bd0->ext_buffer_addr = sc->fw_scripts->ram_code_start_addr;
|
||||
|
||||
WRITE4(sc, SDMAARM_HSTART, 1);
|
||||
|
||||
timeout = 100;
|
||||
while (!(ret = READ4(sc, SDMAARM_INTR) & 1)) {
|
||||
if (timeout-- <= 0)
|
||||
break;
|
||||
DELAY(10);
|
||||
};
|
||||
|
||||
if (ret == 0) {
|
||||
device_printf(sc->dev, "SDMA failed to boot\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
WRITE4(sc, SDMAARM_INTR, ret);
|
||||
|
||||
#if 0
|
||||
device_printf(sc->dev, "SDMA booted successfully.\n");
|
||||
#endif
|
||||
|
||||
/* Debug is disabled */
|
||||
WRITE4(sc, SDMAARM_ONCE_ENB, 0);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
sdma_attach(device_t dev)
|
||||
{
|
||||
struct sdma_softc *sc;
|
||||
int err;
|
||||
|
||||
sc = device_get_softc(dev);
|
||||
sc->dev = dev;
|
||||
|
||||
if (bus_alloc_resources(dev, sdma_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
sdma_sc = sc;
|
||||
|
||||
/* Setup interrupt handler */
|
||||
err = bus_setup_intr(dev, sc->res[1], INTR_TYPE_MISC | INTR_MPSAFE,
|
||||
NULL, sdma_intr, sc, &sc->ih);
|
||||
if (err) {
|
||||
device_printf(dev, "Unable to alloc interrupt resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (load_firmware(sc) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if (boot_firmware(sc) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
return (0);
|
||||
};
|
||||
|
||||
static device_method_t sdma_methods[] = {
|
||||
/* Device interface */
|
||||
DEVMETHOD(device_probe, sdma_probe),
|
||||
DEVMETHOD(device_attach, sdma_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t sdma_driver = {
|
||||
"sdma",
|
||||
sdma_methods,
|
||||
sizeof(struct sdma_softc),
|
||||
};
|
||||
|
||||
static devclass_t sdma_devclass;
|
||||
|
||||
DRIVER_MODULE(sdma, simplebus, sdma_driver, sdma_devclass, 0, 0);
|
245
sys/arm/freescale/imx/imx6_sdma.h
Normal file
245
sys/arm/freescale/imx/imx6_sdma.h
Normal file
@ -0,0 +1,245 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#define SDMAARM_MC0PTR 0x00 /* ARM platform Channel 0 Pointer */
|
||||
#define SDMAARM_INTR 0x04 /* Channel Interrupts */
|
||||
#define SDMAARM_STOP_STAT 0x08 /* Channel Stop/Channel Status */
|
||||
#define SDMAARM_HSTART 0x0C /* Channel Start */
|
||||
#define SDMAARM_EVTOVR 0x10 /* Channel Event Override */
|
||||
#define SDMAARM_DSPOVR 0x14 /* Channel BP Override */
|
||||
#define SDMAARM_HOSTOVR 0x18 /* Channel ARM platform Override */
|
||||
#define SDMAARM_EVTPEND 0x1C /* Channel Event Pending */
|
||||
#define SDMAARM_RESET 0x24 /* Reset Register */
|
||||
#define SDMAARM_EVTERR 0x28 /* DMA Request Error Register */
|
||||
#define SDMAARM_INTRMASK 0x2C /* Channel ARM platform Interrupt Mask */
|
||||
#define SDMAARM_PSW 0x30 /* Schedule Status */
|
||||
#define SDMAARM_EVTERRDBG 0x34 /* DMA Request Error Register */
|
||||
#define SDMAARM_CONFIG 0x38 /* Configuration Register */
|
||||
#define CONFIG_CSM 0x3
|
||||
#define SDMAARM_SDMA_LOCK 0x3C /* SDMA LOCK */
|
||||
#define SDMAARM_ONCE_ENB 0x40 /* OnCE Enable */
|
||||
#define SDMAARM_ONCE_DATA 0x44 /* OnCE Data Register */
|
||||
#define SDMAARM_ONCE_INSTR 0x48 /* OnCE Instruction Register */
|
||||
#define SDMAARM_ONCE_STAT 0x4C /* OnCE Status Register */
|
||||
#define SDMAARM_ONCE_CMD 0x50 /* OnCE Command Register */
|
||||
#define SDMAARM_ILLINSTADDR 0x58 /* Illegal Instruction Trap Address */
|
||||
#define SDMAARM_CHN0ADDR 0x5C /* Channel 0 Boot Address */
|
||||
#define SDMAARM_EVT_MIRROR 0x60 /* DMA Requests */
|
||||
#define SDMAARM_EVT_MIRROR2 0x64 /* DMA Requests 2 */
|
||||
#define SDMAARM_XTRIG_CONF1 0x70 /* Cross-Trigger Events Configuration Register 1 */
|
||||
#define SDMAARM_XTRIG_CONF2 0x74 /* Cross-Trigger Events Configuration Register 2 */
|
||||
#define SDMAARM_SDMA_CHNPRI(n) (0x100 + 0x4 * n) /* Channel Priority Registers */
|
||||
#define SDMAARM_CHNENBL(n) (0x200 + 0x4 * n) /* Channel Enable RAM */
|
||||
|
||||
/* SDMA Event Mappings */
|
||||
#define SSI1_RX_1 35
|
||||
#define SSI1_TX_1 36
|
||||
#define SSI1_RX_0 37
|
||||
#define SSI1_TX_0 38
|
||||
#define SSI2_RX_1 39
|
||||
#define SSI2_TX_1 40
|
||||
#define SSI2_RX_0 41
|
||||
#define SSI2_TX_0 42
|
||||
#define SSI3_RX_1 43
|
||||
#define SSI3_TX_1 44
|
||||
#define SSI3_RX_0 45
|
||||
#define SSI3_TX_0 46
|
||||
|
||||
#define C0_ADDR 0x01
|
||||
#define C0_LOAD 0x02
|
||||
#define C0_DUMP 0x03
|
||||
#define C0_SETCTX 0x07
|
||||
#define C0_GETCTX 0x03
|
||||
#define C0_SETDM 0x01
|
||||
#define C0_SETPM 0x04
|
||||
#define C0_GETDM 0x02
|
||||
#define C0_GETPM 0x08
|
||||
|
||||
#define BD_DONE 0x01
|
||||
#define BD_WRAP 0x02
|
||||
#define BD_CONT 0x04
|
||||
#define BD_INTR 0x08
|
||||
#define BD_RROR 0x10
|
||||
#define BD_LAST 0x20
|
||||
#define BD_EXTD 0x80
|
||||
|
||||
/* sDMA data transfer length */
|
||||
#define CMD_4BYTES 0
|
||||
#define CMD_3BYTES 3
|
||||
#define CMD_2BYTES 2
|
||||
#define CMD_1BYTES 1
|
||||
|
||||
struct sdma_firmware_header {
|
||||
uint32_t magic;
|
||||
uint32_t version_major;
|
||||
uint32_t version_minor;
|
||||
uint32_t script_addrs_start;
|
||||
uint32_t num_script_addrs;
|
||||
uint32_t ram_code_start;
|
||||
uint32_t ram_code_size;
|
||||
};
|
||||
|
||||
struct sdma_mode_count {
|
||||
uint16_t count;
|
||||
uint8_t status;
|
||||
uint8_t command;
|
||||
};
|
||||
|
||||
struct sdma_buffer_descriptor {
|
||||
struct sdma_mode_count mode;
|
||||
uint32_t buffer_addr;
|
||||
uint32_t ext_buffer_addr;
|
||||
} __packed;
|
||||
|
||||
struct sdma_channel_control {
|
||||
uint32_t current_bd_ptr;
|
||||
uint32_t base_bd_ptr;
|
||||
uint32_t unused[2];
|
||||
} __packed;
|
||||
|
||||
struct sdma_state_registers {
|
||||
uint32_t pc :14;
|
||||
uint32_t unused1: 1;
|
||||
uint32_t t : 1;
|
||||
uint32_t rpc :14;
|
||||
uint32_t unused0: 1;
|
||||
uint32_t sf : 1;
|
||||
uint32_t spc :14;
|
||||
uint32_t unused2: 1;
|
||||
uint32_t df : 1;
|
||||
uint32_t epc :14;
|
||||
uint32_t lm : 2;
|
||||
} __packed;
|
||||
|
||||
struct sdma_context_data {
|
||||
struct sdma_state_registers channel_state;
|
||||
uint32_t gReg[8];
|
||||
uint32_t mda;
|
||||
uint32_t msa;
|
||||
uint32_t ms;
|
||||
uint32_t md;
|
||||
uint32_t pda;
|
||||
uint32_t psa;
|
||||
uint32_t ps;
|
||||
uint32_t pd;
|
||||
uint32_t ca;
|
||||
uint32_t cs;
|
||||
uint32_t dda;
|
||||
uint32_t dsa;
|
||||
uint32_t ds;
|
||||
uint32_t dd;
|
||||
uint32_t unused[8];
|
||||
} __packed;
|
||||
|
||||
/* SDMA firmware script pointers */
|
||||
struct sdma_script_start_addrs {
|
||||
int32_t ap_2_ap_addr;
|
||||
int32_t ap_2_bp_addr;
|
||||
int32_t ap_2_ap_fixed_addr;
|
||||
int32_t bp_2_ap_addr;
|
||||
int32_t loopback_on_dsp_side_addr;
|
||||
int32_t mcu_interrupt_only_addr;
|
||||
int32_t firi_2_per_addr;
|
||||
int32_t firi_2_mcu_addr;
|
||||
int32_t per_2_firi_addr;
|
||||
int32_t mcu_2_firi_addr;
|
||||
int32_t uart_2_per_addr;
|
||||
int32_t uart_2_mcu_addr;
|
||||
int32_t per_2_app_addr;
|
||||
int32_t mcu_2_app_addr;
|
||||
int32_t per_2_per_addr;
|
||||
int32_t uartsh_2_per_addr;
|
||||
int32_t uartsh_2_mcu_addr;
|
||||
int32_t per_2_shp_addr;
|
||||
int32_t mcu_2_shp_addr;
|
||||
int32_t ata_2_mcu_addr;
|
||||
int32_t mcu_2_ata_addr;
|
||||
int32_t app_2_per_addr;
|
||||
int32_t app_2_mcu_addr;
|
||||
int32_t shp_2_per_addr;
|
||||
int32_t shp_2_mcu_addr;
|
||||
int32_t mshc_2_mcu_addr;
|
||||
int32_t mcu_2_mshc_addr;
|
||||
int32_t spdif_2_mcu_addr;
|
||||
int32_t mcu_2_spdif_addr;
|
||||
int32_t asrc_2_mcu_addr;
|
||||
int32_t ext_mem_2_ipu_addr;
|
||||
int32_t descrambler_addr;
|
||||
int32_t dptc_dvfs_addr;
|
||||
int32_t utra_addr;
|
||||
int32_t ram_code_start_addr;
|
||||
int32_t mcu_2_ssish_addr;
|
||||
int32_t ssish_2_mcu_addr;
|
||||
int32_t hdmi_dma_addr;
|
||||
};
|
||||
|
||||
#define SDMA_N_CHANNELS 32
|
||||
#define SDMA_N_EVENTS 48
|
||||
#define FW_HEADER_MAGIC 0x414d4453
|
||||
|
||||
struct sdma_channel {
|
||||
struct sdma_conf *conf;
|
||||
struct sdma_buffer_descriptor *bd;
|
||||
uint8_t in_use;
|
||||
};
|
||||
|
||||
struct sdma_softc {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
void *ih;
|
||||
struct sdma_channel_control *ccb;
|
||||
struct sdma_buffer_descriptor *bd0;
|
||||
struct sdma_context_data *context;
|
||||
struct sdma_channel channel[SDMA_N_CHANNELS];
|
||||
uint32_t num_bd;
|
||||
uint32_t ccb_phys;
|
||||
uint32_t context_phys;
|
||||
struct sdma_firmware_header *fw_header;
|
||||
struct sdma_script_start_addrs *fw_scripts;
|
||||
};
|
||||
|
||||
struct sdma_conf {
|
||||
bus_addr_t saddr;
|
||||
bus_addr_t daddr;
|
||||
uint32_t word_length;
|
||||
uint32_t nbits;
|
||||
uint32_t command;
|
||||
uint32_t num_bd;
|
||||
uint32_t event;
|
||||
uint32_t period;
|
||||
uint32_t (*ih)(void *, int);
|
||||
void *ih_user;
|
||||
};
|
||||
|
||||
int sdma_configure(int, struct sdma_conf *);
|
||||
int sdma_start(int);
|
||||
int sdma_stop(int);
|
||||
int sdma_alloc(void);
|
||||
int sdma_free(int);
|
855
sys/arm/freescale/imx/imx6_ssi.c
Normal file
855
sys/arm/freescale/imx/imx6_ssi.c
Normal file
@ -0,0 +1,855 @@
|
||||
/*-
|
||||
* Copyright (c) 2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* 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.
|
||||
*/
|
||||
|
||||
/*
|
||||
* i.MX6 Synchronous Serial Interface (SSI)
|
||||
*
|
||||
* Chapter 61, i.MX 6Dual/6Quad Applications Processor Reference Manual,
|
||||
* Rev. 1, 04/2013
|
||||
*/
|
||||
|
||||
#include <sys/cdefs.h>
|
||||
__FBSDID("$FreeBSD$");
|
||||
|
||||
#include <sys/param.h>
|
||||
#include <sys/systm.h>
|
||||
#include <sys/bus.h>
|
||||
#include <sys/kernel.h>
|
||||
#include <sys/module.h>
|
||||
#include <sys/malloc.h>
|
||||
#include <sys/rman.h>
|
||||
#include <sys/timeet.h>
|
||||
#include <sys/timetc.h>
|
||||
|
||||
#include <dev/sound/pcm/sound.h>
|
||||
#include <dev/sound/chip.h>
|
||||
#include <mixer_if.h>
|
||||
|
||||
#include <dev/fdt/fdt_common.h>
|
||||
#include <dev/ofw/openfirm.h>
|
||||
#include <dev/ofw/ofw_bus.h>
|
||||
#include <dev/ofw/ofw_bus_subr.h>
|
||||
|
||||
#include <machine/bus.h>
|
||||
#include <machine/fdt.h>
|
||||
#include <machine/cpu.h>
|
||||
#include <machine/intr.h>
|
||||
|
||||
#include <arm/freescale/imx/imx6_sdma.h>
|
||||
#include <arm/freescale/imx/imx6_anatopvar.h>
|
||||
#include <arm/freescale/imx/imx_ccmvar.h>
|
||||
|
||||
#define READ4(_sc, _reg) \
|
||||
bus_space_read_4(_sc->bst, _sc->bsh, _reg)
|
||||
#define WRITE4(_sc, _reg, _val) \
|
||||
bus_space_write_4(_sc->bst, _sc->bsh, _reg, _val)
|
||||
|
||||
#define SSI_NCHANNELS 1
|
||||
|
||||
/* i.MX6 SSI registers */
|
||||
|
||||
#define SSI_STX0 0x00 /* Transmit Data Register n */
|
||||
#define SSI_STX1 0x04 /* Transmit Data Register n */
|
||||
#define SSI_SRX0 0x08 /* Receive Data Register n */
|
||||
#define SSI_SRX1 0x0C /* Receive Data Register n */
|
||||
#define SSI_SCR 0x10 /* Control Register */
|
||||
#define SCR_I2S_MODE_S 5 /* I2S Mode Select. */
|
||||
#define SCR_I2S_MODE_M 0x3
|
||||
#define SCR_SYN (1 << 4)
|
||||
#define SCR_NET (1 << 3) /* Network mode */
|
||||
#define SCR_RE (1 << 2) /* Receive Enable. */
|
||||
#define SCR_TE (1 << 1) /* Transmit Enable. */
|
||||
#define SCR_SSIEN (1 << 0) /* SSI Enable */
|
||||
#define SSI_SISR 0x14 /* Interrupt Status Register */
|
||||
#define SSI_SIER 0x18 /* Interrupt Enable Register */
|
||||
#define SIER_RDMAE (1 << 22) /* Receive DMA Enable. */
|
||||
#define SIER_RIE (1 << 21) /* Receive Interrupt Enable. */
|
||||
#define SIER_TDMAE (1 << 20) /* Transmit DMA Enable. */
|
||||
#define SIER_TIE (1 << 19) /* Transmit Interrupt Enable. */
|
||||
#define SIER_TDE0IE (1 << 12) /* Transmit Data Register Empty 0. */
|
||||
#define SIER_TUE0IE (1 << 8) /* Transmitter Underrun Error 0. */
|
||||
#define SIER_TFE0IE (1 << 0) /* Transmit FIFO Empty 0 IE. */
|
||||
#define SSI_STCR 0x1C /* Transmit Configuration Register */
|
||||
#define STCR_TXBIT0 (1 << 9) /* Transmit Bit 0 shift MSB/LSB */
|
||||
#define STCR_TFEN1 (1 << 8) /* Transmit FIFO Enable 1. */
|
||||
#define STCR_TFEN0 (1 << 7) /* Transmit FIFO Enable 0. */
|
||||
#define STCR_TFDIR (1 << 6) /* Transmit Frame Direction. */
|
||||
#define STCR_TXDIR (1 << 5) /* Transmit Clock Direction. */
|
||||
#define STCR_TSHFD (1 << 4) /* Transmit Shift Direction. */
|
||||
#define STCR_TSCKP (1 << 3) /* Transmit Clock Polarity. */
|
||||
#define STCR_TFSI (1 << 2) /* Transmit Frame Sync Invert. */
|
||||
#define STCR_TFSL (1 << 1) /* Transmit Frame Sync Length. */
|
||||
#define STCR_TEFS (1 << 0) /* Transmit Early Frame Sync. */
|
||||
#define SSI_SRCR 0x20 /* Receive Configuration Register */
|
||||
#define SSI_STCCR 0x24 /* Transmit Clock Control Register */
|
||||
#define STCCR_DIV2 (1 << 18) /* Divide By 2. */
|
||||
#define STCCR_PSR (1 << 17) /* Divide clock by 8. */
|
||||
#define WL3_WL0_S 13
|
||||
#define WL3_WL0_M 0xf
|
||||
#define DC4_DC0_S 8
|
||||
#define DC4_DC0_M 0x1f
|
||||
#define PM7_PM0_S 0
|
||||
#define PM7_PM0_M 0xff
|
||||
#define SSI_SRCCR 0x28 /* Receive Clock Control Register */
|
||||
#define SSI_SFCSR 0x2C /* FIFO Control/Status Register */
|
||||
#define SFCSR_RFWM1_S 20 /* Receive FIFO Empty WaterMark 1 */
|
||||
#define SFCSR_RFWM1_M 0xf
|
||||
#define SFCSR_TFWM1_S 16 /* Transmit FIFO Empty WaterMark 1 */
|
||||
#define SFCSR_TFWM1_M 0xf
|
||||
#define SFCSR_RFWM0_S 4 /* Receive FIFO Empty WaterMark 0 */
|
||||
#define SFCSR_RFWM0_M 0xf
|
||||
#define SFCSR_TFWM0_S 0 /* Transmit FIFO Empty WaterMark 0 */
|
||||
#define SFCSR_TFWM0_M 0xf
|
||||
#define SSI_SACNT 0x38 /* AC97 Control Register */
|
||||
#define SSI_SACADD 0x3C /* AC97 Command Address Register */
|
||||
#define SSI_SACDAT 0x40 /* AC97 Command Data Register */
|
||||
#define SSI_SATAG 0x44 /* AC97 Tag Register */
|
||||
#define SSI_STMSK 0x48 /* Transmit Time Slot Mask Register */
|
||||
#define SSI_SRMSK 0x4C /* Receive Time Slot Mask Register */
|
||||
#define SSI_SACCST 0x50 /* AC97 Channel Status Register */
|
||||
#define SSI_SACCEN 0x54 /* AC97 Channel Enable Register */
|
||||
#define SSI_SACCDIS 0x58 /* AC97 Channel Disable Register */
|
||||
|
||||
static MALLOC_DEFINE(M_SSI, "ssi", "ssi audio");
|
||||
|
||||
uint32_t ssi_dma_intr(void *arg, int chn);
|
||||
|
||||
struct ssi_rate {
|
||||
uint32_t speed;
|
||||
uint32_t mfi; /* PLL4 Multiplication Factor Integer */
|
||||
uint32_t mfn; /* PLL4 Multiplication Factor Numerator */
|
||||
uint32_t mfd; /* PLL4 Multiplication Factor Denominator */
|
||||
/* More dividers to configure can be added here */
|
||||
};
|
||||
|
||||
static struct ssi_rate rate_map[] = {
|
||||
{ 192000, 49, 152, 1000 }, /* PLL4 49.152 Mhz */
|
||||
/* TODO: add more frequences */
|
||||
{ 0, 0 },
|
||||
};
|
||||
|
||||
/*
|
||||
* i.MX6 example bit clock formula
|
||||
*
|
||||
* BCLK = 2 channels * 192000 hz * 24 bit = 9216000 hz =
|
||||
* (24000000 * (49 + 152/1000.0) / 4 / 4 / 2 / 2 / 2 / 1 / 1)
|
||||
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
||||
* | | | | | | | | | | |
|
||||
* Fref ------/ | | | | | | | | | |
|
||||
* PLL4 div select -/ | | | | | | | | |
|
||||
* PLL4 num --------------/ | | | | | | | |
|
||||
* PLL4 denom -------------------/ | | | | | | |
|
||||
* PLL4 post div ---------------------/ | | | | | |
|
||||
* CCM ssi pre div (CCM_CS1CDR) ----------/ | | | | |
|
||||
* CCM ssi post div (CCM_CS1CDR) -------------/ | | | |
|
||||
* SSI PM7_PM0_S ---------------------------------/ | | |
|
||||
* SSI Fixed divider ---------------------------------/ | |
|
||||
* SSI DIV2 ----------------------------------------------/ |
|
||||
* SSI PSR (prescaler /1 or /8) ------------------------------/
|
||||
*
|
||||
* MCLK (Master clock) depends on DAC, usually BCLK * 4
|
||||
*/
|
||||
|
||||
struct sc_info {
|
||||
struct resource *res[2];
|
||||
bus_space_tag_t bst;
|
||||
bus_space_handle_t bsh;
|
||||
device_t dev;
|
||||
struct mtx *lock;
|
||||
void *ih;
|
||||
int pos;
|
||||
int dma_size;
|
||||
bus_dma_tag_t dma_tag;
|
||||
bus_dmamap_t dma_map;
|
||||
bus_addr_t buf_base_phys;
|
||||
uint32_t *buf_base;
|
||||
struct sdma_conf *conf;
|
||||
struct ssi_rate *sr;
|
||||
struct sdma_softc *sdma_sc;
|
||||
int sdma_ev_rx;
|
||||
int sdma_ev_tx;
|
||||
int sdma_channel;
|
||||
};
|
||||
|
||||
/* Channel registers */
|
||||
struct sc_chinfo {
|
||||
struct snd_dbuf *buffer;
|
||||
struct pcm_channel *channel;
|
||||
struct sc_pcminfo *parent;
|
||||
|
||||
/* Channel information */
|
||||
uint32_t dir;
|
||||
uint32_t format;
|
||||
|
||||
/* Flags */
|
||||
uint32_t run;
|
||||
};
|
||||
|
||||
/* PCM device private data */
|
||||
struct sc_pcminfo {
|
||||
device_t dev;
|
||||
uint32_t (*ih)(struct sc_pcminfo *scp);
|
||||
uint32_t chnum;
|
||||
struct sc_chinfo chan[SSI_NCHANNELS];
|
||||
struct sc_info *sc;
|
||||
};
|
||||
|
||||
static struct resource_spec ssi_spec[] = {
|
||||
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
|
||||
{ SYS_RES_IRQ, 0, RF_ACTIVE },
|
||||
{ -1, 0 }
|
||||
};
|
||||
|
||||
static int setup_dma(struct sc_pcminfo *scp);
|
||||
static void setup_ssi(struct sc_info *);
|
||||
static void ssi_configure_clock(struct sc_info *);
|
||||
|
||||
/*
|
||||
* Mixer interface.
|
||||
*/
|
||||
|
||||
static int
|
||||
ssimixer_init(struct snd_mixer *m)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_info *sc;
|
||||
int mask;
|
||||
|
||||
scp = mix_getdevinfo(m);
|
||||
sc = scp->sc;
|
||||
|
||||
if (sc == NULL)
|
||||
return -1;
|
||||
|
||||
mask = SOUND_MASK_PCM;
|
||||
mask |= SOUND_MASK_VOLUME;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
pcm_setflags(scp->dev, pcm_getflags(scp->dev) | SD_F_SOFTPCMVOL);
|
||||
mix_setdevs(m, mask);
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ssimixer_set(struct snd_mixer *m, unsigned dev,
|
||||
unsigned left, unsigned right)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
|
||||
scp = mix_getdevinfo(m);
|
||||
|
||||
/* Here we can configure hardware volume on our DAC */
|
||||
|
||||
#if 1
|
||||
device_printf(scp->dev, "ssimixer_set() %d %d\n",
|
||||
left, right);
|
||||
#endif
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static kobj_method_t ssimixer_methods[] = {
|
||||
KOBJMETHOD(mixer_init, ssimixer_init),
|
||||
KOBJMETHOD(mixer_set, ssimixer_set),
|
||||
KOBJMETHOD_END
|
||||
};
|
||||
MIXER_DECLARE(ssimixer);
|
||||
|
||||
|
||||
/*
|
||||
* Channel interface.
|
||||
*/
|
||||
|
||||
static void *
|
||||
ssichan_init(kobj_t obj, void *devinfo, struct snd_dbuf *b,
|
||||
struct pcm_channel *c, int dir)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
|
||||
scp = (struct sc_pcminfo *)devinfo;
|
||||
sc = scp->sc;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
ch = &scp->chan[0];
|
||||
ch->dir = dir;
|
||||
ch->run = 0;
|
||||
ch->buffer = b;
|
||||
ch->channel = c;
|
||||
ch->parent = scp;
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
if (sndbuf_setup(ch->buffer, sc->buf_base, sc->dma_size) != 0) {
|
||||
device_printf(scp->dev, "Can't setup sndbuf.\n");
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return ch;
|
||||
}
|
||||
|
||||
static int
|
||||
ssichan_free(kobj_t obj, void *data)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
struct sc_pcminfo *scp = ch->parent;
|
||||
struct sc_info *sc = scp->sc;
|
||||
|
||||
#if 0
|
||||
device_printf(scp->dev, "ssichan_free()\n");
|
||||
#endif
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
/* TODO: free channel buffer */
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ssichan_setformat(kobj_t obj, void *data, uint32_t format)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
|
||||
ch->format = format;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ssichan_setspeed(kobj_t obj, void *data, uint32_t speed)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_chinfo *ch;
|
||||
struct ssi_rate *sr;
|
||||
struct sc_info *sc;
|
||||
int threshold;
|
||||
int i;
|
||||
|
||||
ch = data;
|
||||
scp = ch->parent;
|
||||
sc = scp->sc;
|
||||
|
||||
sr = NULL;
|
||||
|
||||
/* First look for equal frequency. */
|
||||
for (i = 0; rate_map[i].speed != 0; i++) {
|
||||
if (rate_map[i].speed == speed)
|
||||
sr = &rate_map[i];
|
||||
}
|
||||
|
||||
/* If no match, just find nearest. */
|
||||
if (sr == NULL) {
|
||||
for (i = 0; rate_map[i].speed != 0; i++) {
|
||||
sr = &rate_map[i];
|
||||
threshold = sr->speed + ((rate_map[i + 1].speed != 0) ?
|
||||
((rate_map[i + 1].speed - sr->speed) >> 1) : 0);
|
||||
if (speed < threshold)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sc->sr = sr;
|
||||
|
||||
ssi_configure_clock(sc);
|
||||
|
||||
return (sr->speed);
|
||||
}
|
||||
|
||||
static void
|
||||
ssi_configure_clock(struct sc_info *sc)
|
||||
{
|
||||
struct ssi_rate *sr;
|
||||
|
||||
sr = sc->sr;
|
||||
|
||||
pll4_configure_output(sr->mfi, sr->mfn, sr->mfd);
|
||||
|
||||
/* Configure other dividers here, if any */
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ssichan_setblocksize(kobj_t obj, void *data, uint32_t blocksize)
|
||||
{
|
||||
struct sc_chinfo *ch = data;
|
||||
struct sc_pcminfo *scp = ch->parent;
|
||||
struct sc_info *sc = scp->sc;
|
||||
|
||||
sndbuf_resize(ch->buffer, sc->dma_size / blocksize, blocksize);
|
||||
|
||||
setup_dma(scp);
|
||||
|
||||
return (sndbuf_getblksz(ch->buffer));
|
||||
}
|
||||
|
||||
uint32_t
|
||||
ssi_dma_intr(void *arg, int chn)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sdma_conf *conf;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
int bufsize;
|
||||
|
||||
scp = arg;
|
||||
ch = &scp->chan[0];
|
||||
sc = scp->sc;
|
||||
conf = sc->conf;
|
||||
|
||||
bufsize = sndbuf_getsize(ch->buffer);
|
||||
|
||||
sc->pos += conf->period;
|
||||
if (sc->pos >= bufsize)
|
||||
sc->pos -= bufsize;
|
||||
|
||||
if (ch->run)
|
||||
chn_intr(ch->channel);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
find_sdma_controller(struct sc_info *sc)
|
||||
{
|
||||
struct sdma_softc *sdma_sc;
|
||||
phandle_t node, sdma_node;
|
||||
device_t sdma_dev;
|
||||
int dts_value[8];
|
||||
int len;
|
||||
|
||||
if ((node = ofw_bus_get_node(sc->dev)) == -1)
|
||||
return (ENXIO);
|
||||
|
||||
if ((len = OF_getproplen(node, "dmas")) <= 0)
|
||||
return (ENXIO);
|
||||
|
||||
OF_getprop(node, "dmas", &dts_value, len);
|
||||
|
||||
sc->sdma_ev_rx = fdt32_to_cpu(dts_value[1]);
|
||||
sc->sdma_ev_tx = fdt32_to_cpu(dts_value[5]);
|
||||
|
||||
sdma_node = OF_node_from_xref(fdt32_to_cpu(dts_value[0]));
|
||||
|
||||
sdma_sc = NULL;
|
||||
|
||||
sdma_dev = devclass_get_device(devclass_find("sdma"), 0);
|
||||
if (sdma_dev)
|
||||
sdma_sc = device_get_softc(sdma_dev);
|
||||
|
||||
if (sdma_sc == NULL) {
|
||||
device_printf(sc->dev, "No sDMA found. Can't operate\n");
|
||||
return (ENXIO);
|
||||
};
|
||||
|
||||
sc->sdma_sc = sdma_sc;
|
||||
|
||||
return (0);
|
||||
};
|
||||
|
||||
static int
|
||||
setup_dma(struct sc_pcminfo *scp)
|
||||
{
|
||||
struct sdma_conf *conf;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
int fmt;
|
||||
|
||||
ch = &scp->chan[0];
|
||||
sc = scp->sc;
|
||||
conf = sc->conf;
|
||||
|
||||
conf->ih = ssi_dma_intr;
|
||||
conf->ih_user = scp;
|
||||
conf->saddr = sc->buf_base_phys;
|
||||
conf->daddr = rman_get_start(sc->res[0]) + SSI_STX0;
|
||||
conf->event = sc->sdma_ev_tx; /* SDMA TX event */
|
||||
conf->period = sndbuf_getblksz(ch->buffer);
|
||||
conf->num_bd = sndbuf_getblkcnt(ch->buffer);
|
||||
|
||||
/*
|
||||
* Word Length
|
||||
* Can be 32, 24, 16 or 8 for sDMA.
|
||||
*
|
||||
* SSI supports 24 at max.
|
||||
*/
|
||||
|
||||
fmt = sndbuf_getfmt(ch->buffer);
|
||||
|
||||
if (fmt & AFMT_16BIT) {
|
||||
conf->word_length = 16;
|
||||
conf->command = CMD_2BYTES;
|
||||
} else if (fmt & AFMT_24BIT) {
|
||||
conf->word_length = 24;
|
||||
conf->command = CMD_3BYTES;
|
||||
} else {
|
||||
device_printf(sc->dev, "Unknown format\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ssi_start(struct sc_pcminfo *scp)
|
||||
{
|
||||
struct sc_info *sc;
|
||||
int reg;
|
||||
|
||||
sc = scp->sc;
|
||||
|
||||
if (sdma_configure(sc->sdma_channel, sc->conf) != 0) {
|
||||
device_printf(sc->dev, "Can't configure sDMA\n");
|
||||
return (-1);
|
||||
}
|
||||
|
||||
/* Enable DMA interrupt */
|
||||
reg = (SIER_TDMAE);
|
||||
WRITE4(sc, SSI_SIER, reg);
|
||||
|
||||
sdma_start(sc->sdma_channel);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ssi_stop(struct sc_pcminfo *scp)
|
||||
{
|
||||
struct sc_info *sc;
|
||||
int reg;
|
||||
|
||||
sc = scp->sc;
|
||||
|
||||
reg = READ4(sc, SSI_SIER);
|
||||
reg &= ~(SIER_TDMAE);
|
||||
WRITE4(sc, SSI_SIER, reg);
|
||||
|
||||
sdma_stop(sc->sdma_channel);
|
||||
|
||||
bzero(sc->buf_base, sc->dma_size);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static int
|
||||
ssichan_trigger(kobj_t obj, void *data, int go)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
|
||||
ch = data;
|
||||
scp = ch->parent;
|
||||
sc = scp->sc;
|
||||
|
||||
snd_mtxlock(sc->lock);
|
||||
|
||||
switch (go) {
|
||||
case PCMTRIG_START:
|
||||
#if 0
|
||||
device_printf(scp->dev, "trigger start\n");
|
||||
#endif
|
||||
ch->run = 1;
|
||||
|
||||
ssi_start(scp);
|
||||
|
||||
break;
|
||||
|
||||
case PCMTRIG_STOP:
|
||||
case PCMTRIG_ABORT:
|
||||
#if 0
|
||||
device_printf(scp->dev, "trigger stop or abort\n");
|
||||
#endif
|
||||
ch->run = 0;
|
||||
|
||||
ssi_stop(scp);
|
||||
|
||||
break;
|
||||
}
|
||||
|
||||
snd_mtxunlock(sc->lock);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static uint32_t
|
||||
ssichan_getptr(kobj_t obj, void *data)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
|
||||
ch = data;
|
||||
scp = ch->parent;
|
||||
sc = scp->sc;
|
||||
|
||||
return (sc->pos);
|
||||
}
|
||||
|
||||
static uint32_t ssi_pfmt[] = {
|
||||
SND_FORMAT(AFMT_S24_LE, 2, 0),
|
||||
0
|
||||
};
|
||||
|
||||
static struct pcmchan_caps ssi_pcaps = {44100, 192000, ssi_pfmt, 0};
|
||||
|
||||
static struct pcmchan_caps *
|
||||
ssichan_getcaps(kobj_t obj, void *data)
|
||||
{
|
||||
|
||||
return (&ssi_pcaps);
|
||||
}
|
||||
|
||||
static kobj_method_t ssichan_methods[] = {
|
||||
KOBJMETHOD(channel_init, ssichan_init),
|
||||
KOBJMETHOD(channel_free, ssichan_free),
|
||||
KOBJMETHOD(channel_setformat, ssichan_setformat),
|
||||
KOBJMETHOD(channel_setspeed, ssichan_setspeed),
|
||||
KOBJMETHOD(channel_setblocksize, ssichan_setblocksize),
|
||||
KOBJMETHOD(channel_trigger, ssichan_trigger),
|
||||
KOBJMETHOD(channel_getptr, ssichan_getptr),
|
||||
KOBJMETHOD(channel_getcaps, ssichan_getcaps),
|
||||
KOBJMETHOD_END
|
||||
};
|
||||
CHANNEL_DECLARE(ssichan);
|
||||
|
||||
static int
|
||||
ssi_probe(device_t dev)
|
||||
{
|
||||
|
||||
if (!ofw_bus_status_okay(dev))
|
||||
return (ENXIO);
|
||||
|
||||
if (!ofw_bus_is_compatible(dev, "fsl,imx6q-ssi"))
|
||||
return (ENXIO);
|
||||
|
||||
device_set_desc(dev, "i.MX6 Synchronous Serial Interface (SSI)");
|
||||
return (BUS_PROBE_DEFAULT);
|
||||
}
|
||||
|
||||
static void
|
||||
ssi_intr(void *arg)
|
||||
{
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_chinfo *ch;
|
||||
struct sc_info *sc;
|
||||
|
||||
scp = arg;
|
||||
sc = scp->sc;
|
||||
ch = &scp->chan[0];
|
||||
|
||||
/* We don't use SSI interrupt */
|
||||
#if 0
|
||||
device_printf(sc->dev, "SSI Intr 0x%08x\n",
|
||||
READ4(sc, SSI_SISR));
|
||||
#endif
|
||||
}
|
||||
|
||||
static void
|
||||
setup_ssi(struct sc_info *sc)
|
||||
{
|
||||
int reg;
|
||||
|
||||
reg = READ4(sc, SSI_STCCR);
|
||||
reg &= ~(WL3_WL0_M << WL3_WL0_S);
|
||||
reg |= (0xb << WL3_WL0_S); /* 24 bit */
|
||||
reg &= ~(DC4_DC0_M << DC4_DC0_S);
|
||||
reg |= (1 << DC4_DC0_S); /* 2 words per frame */
|
||||
reg &= ~(STCCR_DIV2); /* Divide by 1 */
|
||||
reg &= ~(STCCR_PSR); /* Divide by 1 */
|
||||
reg &= ~(PM7_PM0_M << PM7_PM0_S);
|
||||
reg |= (1 << PM7_PM0_S); /* Divide by 2 */
|
||||
WRITE4(sc, SSI_STCCR, reg);
|
||||
|
||||
reg = READ4(sc, SSI_SFCSR);
|
||||
reg &= ~(SFCSR_TFWM0_M << SFCSR_TFWM0_S);
|
||||
reg |= (8 << SFCSR_TFWM0_S); /* empty slots */
|
||||
WRITE4(sc, SSI_SFCSR, reg);
|
||||
|
||||
reg = READ4(sc, SSI_STCR);
|
||||
reg |= (STCR_TFEN0);
|
||||
reg &= ~(STCR_TFEN1);
|
||||
reg &= ~(STCR_TSHFD); /* MSB */
|
||||
reg |= (STCR_TXBIT0);
|
||||
reg |= (STCR_TXDIR | STCR_TFDIR);
|
||||
reg |= (STCR_TSCKP); /* falling edge */
|
||||
reg |= (STCR_TFSI);
|
||||
reg &= ~(STCR_TFSI); /* active high frame sync */
|
||||
reg &= ~(STCR_TFSL);
|
||||
reg |= STCR_TEFS;
|
||||
WRITE4(sc, SSI_STCR, reg);
|
||||
|
||||
reg = READ4(sc, SSI_SCR);
|
||||
reg &= ~(SCR_I2S_MODE_M << SCR_I2S_MODE_S); /* Not master */
|
||||
reg |= (SCR_SSIEN | SCR_TE);
|
||||
reg |= (SCR_NET);
|
||||
reg |= (SCR_SYN);
|
||||
WRITE4(sc, SSI_SCR, reg);
|
||||
}
|
||||
|
||||
static void
|
||||
ssi_dmamap_cb(void *arg, bus_dma_segment_t *segs, int nseg, int err)
|
||||
{
|
||||
bus_addr_t *addr;
|
||||
|
||||
if (err)
|
||||
return;
|
||||
|
||||
addr = (bus_addr_t*)arg;
|
||||
*addr = segs[0].ds_addr;
|
||||
}
|
||||
|
||||
static int
|
||||
ssi_attach(device_t dev)
|
||||
{
|
||||
char status[SND_STATUSLEN];
|
||||
struct sc_pcminfo *scp;
|
||||
struct sc_info *sc;
|
||||
int err;
|
||||
|
||||
sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
sc->dev = dev;
|
||||
sc->sr = &rate_map[0];
|
||||
sc->pos = 0;
|
||||
sc->conf = malloc(sizeof(struct sdma_conf), M_DEVBUF, M_WAITOK | M_ZERO);
|
||||
|
||||
sc->lock = snd_mtxcreate(device_get_nameunit(dev), "ssi softc");
|
||||
if (sc->lock == NULL) {
|
||||
device_printf(dev, "Cant create mtx\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
if (bus_alloc_resources(dev, ssi_spec, sc->res)) {
|
||||
device_printf(dev, "could not allocate resources\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Memory interface */
|
||||
sc->bst = rman_get_bustag(sc->res[0]);
|
||||
sc->bsh = rman_get_bushandle(sc->res[0]);
|
||||
|
||||
/* SDMA */
|
||||
if (find_sdma_controller(sc)) {
|
||||
device_printf(dev, "could not find active SDMA\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
/* Setup PCM */
|
||||
scp = malloc(sizeof(struct sc_pcminfo), M_DEVBUF, M_NOWAIT | M_ZERO);
|
||||
scp->sc = sc;
|
||||
scp->dev = dev;
|
||||
|
||||
/*
|
||||
* Maximum possible DMA buffer.
|
||||
* Will be used partialy to match 24 bit word.
|
||||
*/
|
||||
sc->dma_size = 131072;
|
||||
|
||||
/*
|
||||
* Must use dma_size boundary as modulo feature required.
|
||||
* Modulo feature allows setup circular buffer.
|
||||
*/
|
||||
|
||||
err = bus_dma_tag_create(
|
||||
bus_get_dma_tag(sc->dev),
|
||||
4, sc->dma_size, /* alignment, boundary */
|
||||
BUS_SPACE_MAXADDR_32BIT, /* lowaddr */
|
||||
BUS_SPACE_MAXADDR, /* highaddr */
|
||||
NULL, NULL, /* filter, filterarg */
|
||||
sc->dma_size, 1, /* maxsize, nsegments */
|
||||
sc->dma_size, 0, /* maxsegsize, flags */
|
||||
NULL, NULL, /* lockfunc, lockarg */
|
||||
&sc->dma_tag);
|
||||
|
||||
err = bus_dmamem_alloc(sc->dma_tag, (void **)&sc->buf_base,
|
||||
BUS_DMA_NOWAIT | BUS_DMA_COHERENT, &sc->dma_map);
|
||||
if (err) {
|
||||
device_printf(dev, "cannot allocate framebuffer\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
err = bus_dmamap_load(sc->dma_tag, sc->dma_map, sc->buf_base,
|
||||
sc->dma_size, ssi_dmamap_cb, &sc->buf_base_phys, BUS_DMA_NOWAIT);
|
||||
if (err) {
|
||||
device_printf(dev, "cannot load DMA map\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
bzero(sc->buf_base, sc->dma_size);
|
||||
|
||||
/* Setup interrupt handler */
|
||||
err = bus_setup_intr(dev, sc->res[1], INTR_MPSAFE | INTR_TYPE_AV,
|
||||
NULL, ssi_intr, scp, &sc->ih);
|
||||
if (err) {
|
||||
device_printf(dev, "Unable to alloc interrupt resource.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
pcm_setflags(dev, pcm_getflags(dev) | SD_F_MPSAFE);
|
||||
|
||||
err = pcm_register(dev, scp, 1, 0);
|
||||
if (err) {
|
||||
device_printf(dev, "Can't register pcm.\n");
|
||||
return (ENXIO);
|
||||
}
|
||||
|
||||
scp->chnum = 0;
|
||||
pcm_addchan(dev, PCMDIR_PLAY, &ssichan_class, scp);
|
||||
scp->chnum++;
|
||||
|
||||
snprintf(status, SND_STATUSLEN, "at simplebus");
|
||||
pcm_setstatus(dev, status);
|
||||
|
||||
mixer_init(dev, &ssimixer_class, scp);
|
||||
setup_ssi(sc);
|
||||
|
||||
imx_ccm_ssi_configure(dev);
|
||||
|
||||
sc->sdma_channel = sdma_alloc();
|
||||
if (sc->sdma_channel < 0) {
|
||||
device_printf(sc->dev, "Can't get sDMA channel\n");
|
||||
return (1);
|
||||
}
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
static device_method_t ssi_pcm_methods[] = {
|
||||
DEVMETHOD(device_probe, ssi_probe),
|
||||
DEVMETHOD(device_attach, ssi_attach),
|
||||
{ 0, 0 }
|
||||
};
|
||||
|
||||
static driver_t ssi_pcm_driver = {
|
||||
"pcm",
|
||||
ssi_pcm_methods,
|
||||
PCM_SOFTC_SIZE,
|
||||
};
|
||||
|
||||
DRIVER_MODULE(ssi, simplebus, ssi_pcm_driver, pcm_devclass, 0, 0);
|
||||
MODULE_DEPEND(ssi, sound, SOUND_MINVER, SOUND_PREFVER, SOUND_MAXVER);
|
||||
MODULE_VERSION(ssi, 1);
|
@ -51,5 +51,6 @@ uint32_t imx_ccm_ahb_hz(void);
|
||||
|
||||
void imx_ccm_usb_enable(device_t _usbdev);
|
||||
void imx_ccm_usbphy_enable(device_t _phydev);
|
||||
void imx_ccm_ssi_configure(device_t _ssidev);
|
||||
|
||||
#endif
|
||||
|
@ -117,10 +117,36 @@ WR4(struct iomux_softc *sc, bus_size_t off, uint32_t val)
|
||||
bus_write_4(sc->mem_res, off, val);
|
||||
}
|
||||
|
||||
static void
|
||||
iomux_configure_input(struct iomux_softc *sc, uint32_t reg, uint32_t val)
|
||||
{
|
||||
u_int select, mask, shift, width;
|
||||
|
||||
/* If register and value are zero, there is nothing to configure. */
|
||||
if (reg == 0 && val == 0)
|
||||
return;
|
||||
|
||||
/*
|
||||
* If the config value has 0xff in the high byte it is encoded:
|
||||
* 31 23 15 7 0
|
||||
* | 0xff | shift | width | select |
|
||||
* We need to mask out the old select value and OR in the new, using a
|
||||
* mask of the given width and shifting the values up by shift.
|
||||
*/
|
||||
if ((val & 0xff000000) == 0xff000000) {
|
||||
select = val & 0x000000ff;
|
||||
width = (val & 0x0000ff00) >> 8;
|
||||
shift = (val & 0x00ff0000) >> 16;
|
||||
mask = ((1u << width) - 1) << shift;
|
||||
val = (RD4(sc, reg) & ~mask) | (select << shift);
|
||||
}
|
||||
WR4(sc, reg, val);
|
||||
}
|
||||
|
||||
static int
|
||||
iomux_configure_pins(device_t dev, phandle_t cfgxref)
|
||||
{
|
||||
struct iomux_softc * sc;
|
||||
struct iomux_softc *sc;
|
||||
struct pincfg *cfgtuples, *cfg;
|
||||
phandle_t cfgnode;
|
||||
int i, ntuples;
|
||||
@ -137,8 +163,7 @@ iomux_configure_pins(device_t dev, phandle_t cfgxref)
|
||||
for (i = 0, cfg = cfgtuples; i < ntuples; i++, cfg++) {
|
||||
sion = (cfg->padconf_val & PADCONF_SION) ? PADMUX_SION : 0;
|
||||
WR4(sc, cfg->mux_reg, cfg->mux_val | sion);
|
||||
if (cfg->input_reg != 0)
|
||||
WR4(sc, cfg->input_reg, cfg->input_val);
|
||||
iomux_configure_input(sc, cfg->input_reg, cfg->input_val);
|
||||
if ((cfg->padconf_val & PADCONF_NONE) == 0)
|
||||
WR4(sc, cfg->padconf_reg, cfg->padconf_val);
|
||||
if (bootverbose) {
|
||||
|
@ -356,6 +356,8 @@ am335x_lcd_intr(void *arg)
|
||||
|
||||
reg = LCD_READ4(sc, LCD_IRQSTATUS);
|
||||
LCD_WRITE4(sc, LCD_IRQSTATUS, reg);
|
||||
/* Read value back to make sure it reached the hardware */
|
||||
reg = LCD_READ4(sc, LCD_IRQSTATUS);
|
||||
|
||||
if (reg & IRQ_SYNC_LOST) {
|
||||
reg = LCD_READ4(sc, LCD_RASTER_CTRL);
|
||||
@ -401,6 +403,8 @@ am335x_lcd_intr(void *arg)
|
||||
|
||||
done:
|
||||
LCD_WRITE4(sc, LCD_END_OF_INT_IND, 0);
|
||||
/* Read value back to make sure it reached the hardware */
|
||||
reg = LCD_READ4(sc, LCD_END_OF_INT_IND);
|
||||
}
|
||||
|
||||
static int
|
||||
|
@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
|
||||
* Copyright (c) 2014-2015 Ruslan Bukin <br@bsdpad.com>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
@ -26,6 +26,8 @@
|
||||
* $FreeBSD$
|
||||
*/
|
||||
|
||||
#include "imx6q-pinfunc.h"
|
||||
|
||||
/dts-v1/;
|
||||
/include/ "imx6.dtsi"
|
||||
|
||||
@ -42,7 +44,20 @@
|
||||
|
||||
SOC: soc@00000000 {
|
||||
aips@02000000 { /* AIPS1 */
|
||||
iomux@020e0000 { status = "okay"; };
|
||||
iomux@020e0000 {
|
||||
status = "okay";
|
||||
pinctrl-names = "default";
|
||||
pinctrl-0 = <&pins_ssi>;
|
||||
pins_ssi: ssi {
|
||||
fsl,pins = <
|
||||
MX6QDL_PAD_DISP0_DAT16__AUD5_TXC 0x130b0
|
||||
MX6QDL_PAD_DISP0_DAT17__AUD5_TXD 0x110b0
|
||||
MX6QDL_PAD_DISP0_DAT18__AUD5_TXFS 0x130b0
|
||||
MX6QDL_PAD_DISP0_DAT19__AUD5_RXD 0x130b0
|
||||
MX6QDL_PAD_GPIO_19__CCM_CLKO1 0x130b0
|
||||
>;
|
||||
};
|
||||
};
|
||||
gpio@0209c000 { status = "okay"; };
|
||||
gpio@020a0000 { status = "okay"; };
|
||||
gpio@020a4000 { status = "okay"; };
|
||||
@ -76,6 +91,7 @@
|
||||
usdhc@02198000 { status = "disabled"; };
|
||||
usdhc@0219c000 { status = "disabled"; };
|
||||
audmux@021d8000 { status = "okay"; };
|
||||
i2c@021a0000 { status = "okay"; };
|
||||
};
|
||||
};
|
||||
|
||||
|
@ -126,11 +126,12 @@
|
||||
gpt: timer@02098000 {
|
||||
compatible = "fsl,imx6q-gpt", "fsl,imx51-gpt";
|
||||
reg = <0x02098000 0x4000>;
|
||||
interrupt-parent = <&gic>; interrupts = <87>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <87>;
|
||||
};
|
||||
|
||||
iomux@020e0000 {
|
||||
compatible = "fsl,imx6q-iomux";
|
||||
compatible = "fsl,imx6q-iomuxc";
|
||||
reg = <0x020e0000 0x4000>;
|
||||
interrupt-parent = <&gic>;
|
||||
interrupts = <32>;
|
||||
@ -311,6 +312,9 @@
|
||||
compatible = "fsl,imx6q-ssi";
|
||||
reg = <0x02028000 0x4000>;
|
||||
interrupts = < 78 >;
|
||||
dmas = <&sdma 37 1 0>,
|
||||
<&sdma 38 1 0>;
|
||||
dma-names = "rx", "tx";
|
||||
status = "disabled";
|
||||
};
|
||||
|
||||
|
@ -233,7 +233,8 @@ fw_init_crom(struct fwohci_softc *sc)
|
||||
src->businfo.cyc_clk_acc = 100;
|
||||
src->businfo.max_rec = sc->maxrec;
|
||||
src->businfo.max_rom = MAXROM_4;
|
||||
src->businfo.generation = 1;
|
||||
#define FW_GENERATION_CHANGEABLE 2
|
||||
src->businfo.generation = FW_GENERATION_CHANGEABLE;
|
||||
src->businfo.link_spd = sc->speed;
|
||||
|
||||
src->businfo.eui64.hi = sc->eui.hi;
|
||||
@ -313,11 +314,14 @@ fw_crom(struct fwohci_softc *sc)
|
||||
src = &sc->crom_src_buf->src;
|
||||
crom_load(src, (uint32_t *)newrom, CROMSIZE);
|
||||
if (bcmp(newrom, sc->config_rom, CROMSIZE) != 0) {
|
||||
/* bump generation and reload */
|
||||
src->businfo.generation ++;
|
||||
/* generation must be between 0x2 and 0xF */
|
||||
/* Bump generation and reload. */
|
||||
src->businfo.generation++;
|
||||
|
||||
/* Handle generation count wraps. */
|
||||
if (src->businfo.generation < 2)
|
||||
src->businfo.generation ++;
|
||||
src->businfo.generation = 2;
|
||||
|
||||
/* Recalculate CRC to account for generation change. */
|
||||
crom_load(src, (uint32_t *)newrom, CROMSIZE);
|
||||
bcopy(newrom, (void *)sc->config_rom, CROMSIZE);
|
||||
}
|
||||
|
@ -916,7 +916,7 @@ tpc_process_b2b(struct tpc_list *list)
|
||||
/*control*/ 0);
|
||||
tiow->io->io_hdr.retries = 3;
|
||||
tiow->lun = dl;
|
||||
tiow->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tior;
|
||||
tiow->io->io_hdr.ctl_private[CTL_PRIV_FRONTEND].ptr = tiow;
|
||||
|
||||
TAILQ_INSERT_TAIL(&tior->run, tiow, rlinks);
|
||||
TAILQ_INSERT_TAIL(prun, tior, rlinks);
|
||||
|
@ -794,7 +794,7 @@ zfs_mknode(znode_t *dzp, vattr_t *vap, dmu_tx_t *tx, cred_t *cr,
|
||||
gen = vap->va_nblocks; /* ditto */
|
||||
} else {
|
||||
obj = 0;
|
||||
gethrestime(&now);
|
||||
vfs_timestamp(&now);
|
||||
gen = dmu_tx_get_txg(tx);
|
||||
}
|
||||
|
||||
@ -1426,7 +1426,7 @@ zfs_tstamp_update_setup(znode_t *zp, uint_t flag, uint64_t mtime[2],
|
||||
{
|
||||
timestruc_t now;
|
||||
|
||||
gethrestime(&now);
|
||||
vfs_timestamp(&now);
|
||||
|
||||
if (have_tx) { /* will sa_bulk_update happen really soon? */
|
||||
zp->z_atime_dirty = 0;
|
||||
|
@ -1299,6 +1299,49 @@ freebsd32_futimesat(struct thread *td, struct freebsd32_futimesat_args *uap)
|
||||
sp, UIO_SYSSPACE));
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_futimens(struct thread *td, struct freebsd32_futimens_args *uap)
|
||||
{
|
||||
struct timespec32 ts32[2];
|
||||
struct timespec ts[2], *tsp;
|
||||
int error;
|
||||
|
||||
if (uap->times != NULL) {
|
||||
error = copyin(uap->times, ts32, sizeof(ts32));
|
||||
if (error)
|
||||
return (error);
|
||||
CP(ts32[0], ts[0], tv_sec);
|
||||
CP(ts32[0], ts[0], tv_nsec);
|
||||
CP(ts32[1], ts[1], tv_sec);
|
||||
CP(ts32[1], ts[1], tv_nsec);
|
||||
tsp = ts;
|
||||
} else
|
||||
tsp = NULL;
|
||||
return (kern_futimens(td, uap->fd, tsp, UIO_SYSSPACE));
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_utimensat(struct thread *td, struct freebsd32_utimensat_args *uap)
|
||||
{
|
||||
struct timespec32 ts32[2];
|
||||
struct timespec ts[2], *tsp;
|
||||
int error;
|
||||
|
||||
if (uap->times != NULL) {
|
||||
error = copyin(uap->times, ts32, sizeof(ts32));
|
||||
if (error)
|
||||
return (error);
|
||||
CP(ts32[0], ts[0], tv_sec);
|
||||
CP(ts32[0], ts[0], tv_nsec);
|
||||
CP(ts32[1], ts[1], tv_sec);
|
||||
CP(ts32[1], ts[1], tv_nsec);
|
||||
tsp = ts;
|
||||
} else
|
||||
tsp = NULL;
|
||||
return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,
|
||||
tsp, UIO_SYSSPACE, uap->flag));
|
||||
}
|
||||
|
||||
int
|
||||
freebsd32_adjtime(struct thread *td, struct freebsd32_adjtime_args *uap)
|
||||
{
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#ifndef _FREEBSD32_SYSPROTO_H_
|
||||
@ -693,6 +693,16 @@ struct freebsd32_ppoll_args {
|
||||
char ts_l_[PADL_(const struct timespec32 *)]; const struct timespec32 * ts; char ts_r_[PADR_(const struct timespec32 *)];
|
||||
char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)];
|
||||
};
|
||||
struct freebsd32_futimens_args {
|
||||
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
|
||||
char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)];
|
||||
};
|
||||
struct freebsd32_utimensat_args {
|
||||
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
|
||||
char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
|
||||
char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)];
|
||||
char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
|
||||
};
|
||||
#if !defined(PAD64_REQUIRED) && (defined(__powerpc__) || defined(__mips__))
|
||||
#define PAD64_REQUIRED
|
||||
#endif
|
||||
@ -825,6 +835,8 @@ int freebsd32_procctl(struct thread *, struct freebsd32_procctl_args *);
|
||||
int freebsd32_procctl(struct thread *, struct freebsd32_procctl_args *);
|
||||
#endif
|
||||
int freebsd32_ppoll(struct thread *, struct freebsd32_ppoll_args *);
|
||||
int freebsd32_futimens(struct thread *, struct freebsd32_futimens_args *);
|
||||
int freebsd32_utimensat(struct thread *, struct freebsd32_utimensat_args *);
|
||||
|
||||
#ifdef COMPAT_43
|
||||
|
||||
@ -1240,6 +1252,8 @@ int freebsd7_freebsd32_shmctl(struct thread *, struct freebsd7_freebsd32_shmctl_
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_procctl AUE_NULL
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_procctl AUE_NULL
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_ppoll AUE_POLL
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_futimens AUE_FUTIMES
|
||||
#define FREEBSD32_SYS_AUE_freebsd32_utimensat AUE_FUTIMESAT
|
||||
|
||||
#undef PAD_
|
||||
#undef PADL_
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#define FREEBSD32_SYS_syscall 0
|
||||
@ -453,4 +453,6 @@
|
||||
#define FREEBSD32_SYS_freebsd32_procctl 544
|
||||
#define FREEBSD32_SYS_freebsd32_procctl 544
|
||||
#define FREEBSD32_SYS_freebsd32_ppoll 545
|
||||
#define FREEBSD32_SYS_MAXSYSCALL 546
|
||||
#define FREEBSD32_SYS_freebsd32_futimens 546
|
||||
#define FREEBSD32_SYS_freebsd32_utimensat 547
|
||||
#define FREEBSD32_SYS_MAXSYSCALL 548
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
const char *freebsd32_syscallnames[] = {
|
||||
@ -579,4 +579,6 @@ const char *freebsd32_syscallnames[] = {
|
||||
"freebsd32_procctl", /* 544 = freebsd32_procctl */
|
||||
#endif
|
||||
"freebsd32_ppoll", /* 545 = freebsd32_ppoll */
|
||||
"freebsd32_futimens", /* 546 = freebsd32_futimens */
|
||||
"freebsd32_utimensat", /* 547 = freebsd32_utimensat */
|
||||
};
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/compat/freebsd32/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
@ -616,4 +616,6 @@ struct sysent freebsd32_sysent[] = {
|
||||
{ AS(freebsd32_procctl_args), (sy_call_t *)freebsd32_procctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = freebsd32_procctl */
|
||||
#endif
|
||||
{ AS(freebsd32_ppoll_args), (sy_call_t *)freebsd32_ppoll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = freebsd32_ppoll */
|
||||
{ AS(freebsd32_futimens_args), (sy_call_t *)freebsd32_futimens, AUE_FUTIMES, NULL, 0, 0, 0, SY_THR_STATIC }, /* 546 = freebsd32_futimens */
|
||||
{ AS(freebsd32_utimensat_args), (sy_call_t *)freebsd32_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 547 = freebsd32_utimensat */
|
||||
};
|
||||
|
@ -3309,6 +3309,24 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
/* freebsd32_futimens */
|
||||
case 546: {
|
||||
struct freebsd32_futimens_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->times; /* struct timespec * */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* freebsd32_utimensat */
|
||||
case 547: {
|
||||
struct freebsd32_utimensat_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->path; /* char * */
|
||||
uarg[2] = (intptr_t) p->times; /* struct timespec * */
|
||||
iarg[3] = p->flag; /* int */
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*n_args = 0;
|
||||
break;
|
||||
@ -8873,6 +8891,38 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* freebsd32_futimens */
|
||||
case 546:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "struct timespec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* freebsd32_utimensat */
|
||||
case 547:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "char *";
|
||||
break;
|
||||
case 2:
|
||||
p = "struct timespec *";
|
||||
break;
|
||||
case 3:
|
||||
p = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -10751,6 +10801,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* freebsd32_futimens */
|
||||
case 546:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* freebsd32_utimensat */
|
||||
case 547:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -1069,3 +1069,8 @@
|
||||
545 AUE_POLL STD { int freebsd32_ppoll(struct pollfd *fds, \
|
||||
u_int nfds, const struct timespec32 *ts, \
|
||||
const sigset_t *set); }
|
||||
546 AUE_FUTIMES STD { int freebsd32_futimens(int fd, \
|
||||
struct timespec *times); }
|
||||
547 AUE_FUTIMESAT STD { int freebsd32_utimensat(int fd, \
|
||||
char *path, \
|
||||
struct timespec *times, int flag); }
|
||||
|
@ -1141,7 +1141,7 @@ dev/cxgb/sys/uipc_mvec.c optional cxgb pci \
|
||||
dev/cxgb/cxgb_t3fw.c optional cxgb cxgb_t3fw \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgb"
|
||||
dev/cxgbe/t4_mp_ring.c optional cxgbe pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgbe -fms-extensions"
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgbe ${GCC_MS_EXTENSIONS}"
|
||||
dev/cxgbe/t4_main.c optional cxgbe pci \
|
||||
compile-with "${NORMAL_C} -I$S/dev/cxgbe"
|
||||
dev/cxgbe/t4_netmap.c optional cxgbe pci \
|
||||
|
@ -620,7 +620,7 @@ EcGpeQueryHandler(void *Context)
|
||||
struct acpi_ec_softc *sc = (struct acpi_ec_softc *)Context;
|
||||
UINT8 Data;
|
||||
ACPI_STATUS Status;
|
||||
int retry, sci_enqueued;
|
||||
int retry;
|
||||
char qxx[5];
|
||||
|
||||
ACPI_FUNCTION_TRACE((char *)(uintptr_t)__func__);
|
||||
@ -641,15 +641,12 @@ EcGpeQueryHandler(void *Context)
|
||||
* that may arise from running the query from causing another query
|
||||
* to be queued, we clear the pending flag only after running it.
|
||||
*/
|
||||
sci_enqueued = sc->ec_sci_pend;
|
||||
for (retry = 0; retry < 2; retry++) {
|
||||
Status = EcCommand(sc, EC_COMMAND_QUERY);
|
||||
if (ACPI_SUCCESS(Status))
|
||||
break;
|
||||
if (ACPI_SUCCESS(EcCheckStatus(sc, "retr_check",
|
||||
if (ACPI_FAILURE(EcCheckStatus(sc, "retr_check",
|
||||
EC_EVENT_INPUT_BUFFER_EMPTY)))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
}
|
||||
sc->ec_sci_pend = FALSE;
|
||||
@ -681,14 +678,6 @@ EcGpeQueryHandler(void *Context)
|
||||
device_printf(sc->ec_dev, "evaluation of query method %s failed: %s\n",
|
||||
qxx, AcpiFormatException(Status));
|
||||
}
|
||||
|
||||
/* Reenable runtime GPE if its execution was deferred. */
|
||||
if (sci_enqueued) {
|
||||
Status = AcpiFinishGpe(sc->ec_gpehandle, sc->ec_gpebit);
|
||||
if (ACPI_FAILURE(Status))
|
||||
device_printf(sc->ec_dev, "reenabling runtime GPE failed: %s\n",
|
||||
AcpiFormatException(Status));
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
@ -722,10 +711,9 @@ EcGpeHandler(ACPI_HANDLE GpeDevice, UINT32 GpeNumber, void *Context)
|
||||
if ((EcStatus & EC_EVENT_SCI) && !sc->ec_sci_pend) {
|
||||
CTR0(KTR_ACPI, "ec gpe queueing query handler");
|
||||
Status = AcpiOsExecute(OSL_GPE_HANDLER, EcGpeQueryHandler, Context);
|
||||
if (ACPI_SUCCESS(Status)) {
|
||||
if (ACPI_SUCCESS(Status))
|
||||
sc->ec_sci_pend = TRUE;
|
||||
return (0);
|
||||
} else
|
||||
else
|
||||
printf("EcGpeHandler: queuing GPE query handler failed\n");
|
||||
}
|
||||
return (ACPI_REENABLE_GPE);
|
||||
@ -973,15 +961,13 @@ EcRead(struct acpi_ec_softc *sc, UINT8 Address, UINT8 *Data)
|
||||
gen_count = sc->ec_gencount;
|
||||
EC_SET_DATA(sc, Address);
|
||||
status = EcWaitEvent(sc, EC_EVENT_OUTPUT_BUFFER_FULL, gen_count);
|
||||
if (ACPI_FAILURE(status)) {
|
||||
if (ACPI_SUCCESS(EcCheckStatus(sc, "retr_check",
|
||||
EC_EVENT_INPUT_BUFFER_EMPTY)))
|
||||
continue;
|
||||
else
|
||||
break;
|
||||
if (ACPI_SUCCESS(status)) {
|
||||
*Data = EC_GET_DATA(sc);
|
||||
return (AE_OK);
|
||||
}
|
||||
*Data = EC_GET_DATA(sc);
|
||||
return (AE_OK);
|
||||
if (ACPI_FAILURE(EcCheckStatus(sc, "retr_check",
|
||||
EC_EVENT_INPUT_BUFFER_EMPTY)))
|
||||
break;
|
||||
}
|
||||
device_printf(sc->ec_dev, "EcRead: failed waiting to get data\n");
|
||||
return (status);
|
||||
|
@ -274,11 +274,11 @@ static u_int32_t
|
||||
agp_nvidia_get_aperture(device_t dev)
|
||||
{
|
||||
switch (pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1) & 0x0f) {
|
||||
case 0: return (512 * 1024 * 1024); break;
|
||||
case 8: return (256 * 1024 * 1024); break;
|
||||
case 12: return (128 * 1024 * 1024); break;
|
||||
case 14: return (64 * 1024 * 1024); break;
|
||||
case 15: return (32 * 1024 * 1024); break;
|
||||
case 0: return (512 * 1024 * 1024);
|
||||
case 8: return (256 * 1024 * 1024);
|
||||
case 12: return (128 * 1024 * 1024);
|
||||
case 14: return (64 * 1024 * 1024);
|
||||
case 15: return (32 * 1024 * 1024);
|
||||
default:
|
||||
device_printf(dev, "Invalid aperture setting 0x%x\n",
|
||||
pci_read_config(dev, AGP_NVIDIA_0_APSIZE, 1));
|
||||
|
@ -875,9 +875,9 @@ int cx_get_port (cx_chan_t *c)
|
||||
|
||||
if (iftype)
|
||||
switch (c->type) {
|
||||
case T_UNIV_V35: return 1; break;
|
||||
case T_UNIV_RS449: return 2; break;
|
||||
default: return -1; break;
|
||||
case T_UNIV_V35: return 1;
|
||||
case T_UNIV_RS449: return 2;
|
||||
default: return -1;
|
||||
}
|
||||
else
|
||||
return 0;
|
||||
|
@ -671,20 +671,16 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
|
||||
* code think there's a PHY here.
|
||||
*/
|
||||
return (BMSR_MEDIAMASK);
|
||||
break;
|
||||
case MII_PHYIDR1:
|
||||
if (DC_IS_PNIC(sc))
|
||||
return (DC_VENDORID_LO);
|
||||
return (DC_VENDORID_DEC);
|
||||
break;
|
||||
case MII_PHYIDR2:
|
||||
if (DC_IS_PNIC(sc))
|
||||
return (DC_DEVICEID_82C168);
|
||||
return (DC_DEVICEID_21143);
|
||||
break;
|
||||
default:
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
return (0);
|
||||
@ -748,7 +744,6 @@ dc_miibus_readreg(device_t dev, int phy, int reg)
|
||||
device_printf(dev, "phy_read: bad phy register %x\n",
|
||||
reg);
|
||||
return (0);
|
||||
break;
|
||||
}
|
||||
|
||||
rval = CSR_READ_4(sc, phy_reg) & 0x0000FFFF;
|
||||
|
@ -149,7 +149,8 @@ void
|
||||
fdt_clock_register_provider(device_t provider)
|
||||
{
|
||||
|
||||
OF_device_register_xref(OF_xref_from_device(provider), provider);
|
||||
OF_device_register_xref(
|
||||
OF_xref_from_node(ofw_bus_get_node(provider)), provider);
|
||||
}
|
||||
|
||||
void
|
||||
|
@ -52,7 +52,7 @@ static struct cdev *memdev, *kmemdev;
|
||||
|
||||
static struct cdevsw mem_cdevsw = {
|
||||
.d_version = D_VERSION,
|
||||
.d_flags = D_MEM|D_NEEDGIANT,
|
||||
.d_flags = D_MEM,
|
||||
.d_open = memopen,
|
||||
.d_read = memrw,
|
||||
.d_write = memrw,
|
||||
|
@ -3075,10 +3075,10 @@ netmap_init(void)
|
||||
#ifdef __FreeBSD__
|
||||
/* support for the 'eternal' flag */
|
||||
netmap_dev = make_dev_credf(MAKEDEV_ETERNAL_KLD,
|
||||
&netmap_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0660,
|
||||
&netmap_cdevsw, 0, NULL, UID_ROOT, GID_WHEEL, 0600,
|
||||
"netmap");
|
||||
#else
|
||||
netmap_dev = make_dev(&netmap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0660,
|
||||
netmap_dev = make_dev(&netmap_cdevsw, 0, UID_ROOT, GID_WHEEL, 0600,
|
||||
"netmap");
|
||||
#endif
|
||||
if (!netmap_dev)
|
||||
|
@ -86,10 +86,6 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
|
||||
int error = 0;
|
||||
vm_offset_t addr;
|
||||
|
||||
/* XXX UPS Why ? */
|
||||
GIANT_REQUIRED;
|
||||
|
||||
|
||||
if (dev2unit(dev) != CDEV_MINOR_MEM && dev2unit(dev) != CDEV_MINOR_KMEM)
|
||||
return EIO;
|
||||
|
||||
|
@ -220,8 +220,9 @@ fsync
|
||||
ftruncate
|
||||
|
||||
##
|
||||
## Allow futimes(2), subject to capability rights.
|
||||
## Allow futimens(2) and futimes(2), subject to capability rights.
|
||||
##
|
||||
futimens
|
||||
futimes
|
||||
|
||||
##
|
||||
@ -453,6 +454,7 @@ readlinkat
|
||||
renameat
|
||||
symlinkat
|
||||
unlinkat
|
||||
utimensat
|
||||
|
||||
##
|
||||
## Allow entry into open(2). This system call will fail, since access to the
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#include "opt_compat.h"
|
||||
@ -580,4 +580,6 @@ struct sysent sysent[] = {
|
||||
{ AS(aio_mlock_args), (sy_call_t *)lkmressys, AUE_NULL, NULL, 0, 0, 0, SY_THR_ABSENT }, /* 543 = aio_mlock */
|
||||
{ AS(procctl_args), (sy_call_t *)sys_procctl, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 544 = procctl */
|
||||
{ AS(ppoll_args), (sy_call_t *)sys_ppoll, AUE_POLL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 545 = ppoll */
|
||||
{ AS(futimens_args), (sy_call_t *)sys_futimens, AUE_FUTIMES, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 546 = futimens */
|
||||
{ AS(utimensat_args), (sy_call_t *)sys_utimensat, AUE_FUTIMESAT, NULL, 0, 0, SYF_CAPENABLED, SY_THR_STATIC }, /* 547 = utimensat */
|
||||
};
|
||||
|
@ -598,7 +598,7 @@ ksprintn(char *nbuf, uintmax_t num, int base, int *lenp, int upper)
|
||||
* the next characters (up to a control character, i.e. a character <= 32),
|
||||
* give the name of the register. Thus:
|
||||
*
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE\n");
|
||||
* kvprintf("reg=%b\n", 3, "\10\2BITTWO\1BITONE");
|
||||
*
|
||||
* would produce output:
|
||||
*
|
||||
@ -911,7 +911,7 @@ reswitch: switch (ch = (u_char)*fmt++) {
|
||||
while (percent < fmt)
|
||||
PCHAR(*percent++);
|
||||
/*
|
||||
* Since we ignore a formatting argument it is no
|
||||
* Since we ignore a formatting argument it is no
|
||||
* longer safe to obey the remaining formatting
|
||||
* arguments as the arguments will no longer match
|
||||
* the format specs.
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
const char *syscallnames[] = {
|
||||
@ -553,4 +553,6 @@ const char *syscallnames[] = {
|
||||
"aio_mlock", /* 543 = aio_mlock */
|
||||
"procctl", /* 544 = procctl */
|
||||
"ppoll", /* 545 = ppoll */
|
||||
"futimens", /* 546 = futimens */
|
||||
"utimensat", /* 547 = utimensat */
|
||||
};
|
||||
|
@ -983,5 +983,10 @@
|
||||
545 AUE_POLL STD { int ppoll(struct pollfd *fds, u_int nfds, \
|
||||
const struct timespec *ts, \
|
||||
const sigset_t *set); }
|
||||
546 AUE_FUTIMES STD { int futimens(int fd, \
|
||||
struct timespec *times); }
|
||||
547 AUE_FUTIMESAT STD { int utimensat(int fd, \
|
||||
char *path, \
|
||||
struct timespec *times, int flag); }
|
||||
; Please copy any additions and changes to the following compatability tables:
|
||||
; sys/compat/freebsd32/syscalls.master
|
||||
|
@ -3382,6 +3382,24 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
/* futimens */
|
||||
case 546: {
|
||||
struct futimens_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->times; /* struct timespec * */
|
||||
*n_args = 2;
|
||||
break;
|
||||
}
|
||||
/* utimensat */
|
||||
case 547: {
|
||||
struct utimensat_args *p = params;
|
||||
iarg[0] = p->fd; /* int */
|
||||
uarg[1] = (intptr_t) p->path; /* char * */
|
||||
uarg[2] = (intptr_t) p->times; /* struct timespec * */
|
||||
iarg[3] = p->flag; /* int */
|
||||
*n_args = 4;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
*n_args = 0;
|
||||
break;
|
||||
@ -9019,6 +9037,38 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* futimens */
|
||||
case 546:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "struct timespec *";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
/* utimensat */
|
||||
case 547:
|
||||
switch(ndx) {
|
||||
case 0:
|
||||
p = "int";
|
||||
break;
|
||||
case 1:
|
||||
p = "char *";
|
||||
break;
|
||||
case 2:
|
||||
p = "struct timespec *";
|
||||
break;
|
||||
case 3:
|
||||
p = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
@ -10962,6 +11012,16 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* futimens */
|
||||
case 546:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
/* utimensat */
|
||||
case 547:
|
||||
if (ndx == 0 || ndx == 1)
|
||||
p = "int";
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
};
|
||||
|
@ -95,10 +95,12 @@ SDT_PROBE_DEFINE2(vfs, , stat, mode, "char *", "int");
|
||||
SDT_PROBE_DEFINE2(vfs, , stat, reg, "char *", "int");
|
||||
|
||||
static int chroot_refuse_vdir_fds(struct filedesc *fdp);
|
||||
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
|
||||
static int kern_chflagsat(struct thread *td, int fd, const char *path,
|
||||
enum uio_seg pathseg, u_long flags, int atflag);
|
||||
static int setfflags(struct thread *td, struct vnode *, u_long);
|
||||
static int getutimes(const struct timeval *, enum uio_seg, struct timespec *);
|
||||
static int getutimens(const struct timespec *, enum uio_seg,
|
||||
struct timespec *, int *);
|
||||
static int setutimes(struct thread *td, struct vnode *,
|
||||
const struct timespec *, int, int);
|
||||
static int vn_access(struct vnode *vp, int user_flags, struct ucred *cred,
|
||||
@ -3007,7 +3009,53 @@ getutimes(usrtvp, tvpseg, tsp)
|
||||
}
|
||||
|
||||
/*
|
||||
* Common implementation code for utimes(), lutimes(), and futimes().
|
||||
* Common implementation code for futimens(), utimensat().
|
||||
*/
|
||||
#define UTIMENS_NULL 0x1
|
||||
#define UTIMENS_EXIT 0x2
|
||||
static int
|
||||
getutimens(const struct timespec *usrtsp, enum uio_seg tspseg,
|
||||
struct timespec *tsp, int *retflags)
|
||||
{
|
||||
struct timespec tsnow;
|
||||
int error;
|
||||
|
||||
vfs_timestamp(&tsnow);
|
||||
*retflags = 0;
|
||||
if (usrtsp == NULL) {
|
||||
tsp[0] = tsnow;
|
||||
tsp[1] = tsnow;
|
||||
*retflags |= UTIMENS_NULL;
|
||||
return (0);
|
||||
}
|
||||
if (tspseg == UIO_SYSSPACE) {
|
||||
tsp[0] = usrtsp[0];
|
||||
tsp[1] = usrtsp[1];
|
||||
} else if ((error = copyin(usrtsp, tsp, sizeof(*tsp) * 2)) != 0)
|
||||
return (error);
|
||||
if (tsp[0].tv_nsec == UTIME_OMIT && tsp[1].tv_nsec == UTIME_OMIT)
|
||||
*retflags |= UTIMENS_EXIT;
|
||||
if (tsp[0].tv_nsec == UTIME_NOW && tsp[1].tv_nsec == UTIME_NOW)
|
||||
*retflags |= UTIMENS_NULL;
|
||||
if (tsp[0].tv_nsec == UTIME_OMIT)
|
||||
tsp[0].tv_sec = VNOVAL;
|
||||
else if (tsp[0].tv_nsec == UTIME_NOW)
|
||||
tsp[0] = tsnow;
|
||||
else if (tsp[0].tv_nsec < 0 || tsp[0].tv_nsec >= 1000000000L)
|
||||
return (EINVAL);
|
||||
if (tsp[1].tv_nsec == UTIME_OMIT)
|
||||
tsp[1].tv_sec = VNOVAL;
|
||||
else if (tsp[1].tv_nsec == UTIME_NOW)
|
||||
tsp[1] = tsnow;
|
||||
else if (tsp[1].tv_nsec < 0 || tsp[1].tv_nsec >= 1000000000L)
|
||||
return (EINVAL);
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
/*
|
||||
* Common implementation code for utimes(), lutimes(), futimes(), futimens(),
|
||||
* and utimensat().
|
||||
*/
|
||||
static int
|
||||
setutimes(td, vp, ts, numtimes, nullflag)
|
||||
@ -3196,6 +3244,80 @@ kern_futimes(struct thread *td, int fd, struct timeval *tptr,
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
sys_futimens(struct thread *td, struct futimens_args *uap)
|
||||
{
|
||||
|
||||
return (kern_futimens(td, uap->fd, uap->times, UIO_USERSPACE));
|
||||
}
|
||||
|
||||
int
|
||||
kern_futimens(struct thread *td, int fd, struct timespec *tptr,
|
||||
enum uio_seg tptrseg)
|
||||
{
|
||||
struct timespec ts[2];
|
||||
struct file *fp;
|
||||
cap_rights_t rights;
|
||||
int error, flags;
|
||||
|
||||
AUDIT_ARG_FD(fd);
|
||||
error = getutimens(tptr, tptrseg, ts, &flags);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
if (flags & UTIMENS_EXIT)
|
||||
return (0);
|
||||
error = getvnode(td->td_proc->p_fd, fd,
|
||||
cap_rights_init(&rights, CAP_FUTIMES), &fp);
|
||||
if (error != 0)
|
||||
return (error);
|
||||
#ifdef AUDIT
|
||||
vn_lock(fp->f_vnode, LK_SHARED | LK_RETRY);
|
||||
AUDIT_ARG_VNODE1(fp->f_vnode);
|
||||
VOP_UNLOCK(fp->f_vnode, 0);
|
||||
#endif
|
||||
error = setutimes(td, fp->f_vnode, ts, 2, flags & UTIMENS_NULL);
|
||||
fdrop(fp, td);
|
||||
return (error);
|
||||
}
|
||||
|
||||
int
|
||||
sys_utimensat(struct thread *td, struct utimensat_args *uap)
|
||||
{
|
||||
|
||||
return (kern_utimensat(td, uap->fd, uap->path, UIO_USERSPACE,
|
||||
uap->times, UIO_USERSPACE, uap->flag));
|
||||
}
|
||||
|
||||
int
|
||||
kern_utimensat(struct thread *td, int fd, char *path, enum uio_seg pathseg,
|
||||
struct timespec *tptr, enum uio_seg tptrseg, int flag)
|
||||
{
|
||||
struct nameidata nd;
|
||||
struct timespec ts[2];
|
||||
int error, flags;
|
||||
|
||||
if (flag & ~AT_SYMLINK_NOFOLLOW)
|
||||
return (EINVAL);
|
||||
|
||||
if ((error = getutimens(tptr, tptrseg, ts, &flags)) != 0)
|
||||
return (error);
|
||||
NDINIT_AT(&nd, LOOKUP, ((flag & AT_SYMLINK_NOFOLLOW) ? NOFOLLOW :
|
||||
FOLLOW) | AUDITVNODE1, pathseg, path, fd, td);
|
||||
if ((error = namei(&nd)) != 0)
|
||||
return (error);
|
||||
/*
|
||||
* We are allowed to call namei() regardless of 2xUTIME_OMIT.
|
||||
* POSIX states:
|
||||
* "If both tv_nsec fields are UTIME_OMIT... EACCESS may be detected."
|
||||
* "Search permission is denied by a component of the path prefix."
|
||||
*/
|
||||
NDFREE(&nd, NDF_ONLY_PNBUF);
|
||||
if ((flags & UTIMENS_EXIT) == 0)
|
||||
error = setutimes(td, nd.ni_vp, ts, 2, flags & UTIMENS_NULL);
|
||||
vrele(nd.ni_vp);
|
||||
return (error);
|
||||
}
|
||||
|
||||
/*
|
||||
* Truncate a file given its path name.
|
||||
*/
|
||||
|
@ -85,8 +85,6 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
|
||||
cnt = 0;
|
||||
error = 0;
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
pmap_page_init(&m);
|
||||
while (uio->uio_resid > 0 && !error) {
|
||||
iov = uio->uio_iov;
|
||||
|
@ -23,6 +23,7 @@ SRCS+= t4_tracer.c
|
||||
# Provide the timestamp of a packet in its header mbuf.
|
||||
#CFLAGS+= -DT4_PKT_TIMESTAMP
|
||||
|
||||
CFLAGS+= -I${CXGBE} -fms-extensions
|
||||
CFLAGS+= -I${CXGBE}
|
||||
|
||||
.include <bsd.kmod.mk>
|
||||
CFLAGS+= ${GCC_MS_EXTENSIONS}
|
||||
|
@ -1702,12 +1702,14 @@ carp_ioctl(struct ifreq *ifr, u_long cmd, struct thread *td)
|
||||
switch (carpr.carpr_state) {
|
||||
case BACKUP:
|
||||
callout_stop(&sc->sc_ad_tmo);
|
||||
carp_set_state(sc, BACKUP, "SIOCSVH");
|
||||
carp_set_state(sc, BACKUP,
|
||||
"user requested via ifconfig");
|
||||
carp_setrun(sc, 0);
|
||||
carp_delroute(sc);
|
||||
break;
|
||||
case MASTER:
|
||||
carp_master_down_locked(sc, "SIOCSVH");
|
||||
carp_master_down_locked(sc,
|
||||
"user requested via ifconfig");
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
@ -1999,13 +2001,13 @@ carp_sc_state(struct carp_softc *sc)
|
||||
#ifdef INET6
|
||||
callout_stop(&sc->sc_md6_tmo);
|
||||
#endif
|
||||
carp_set_state(sc, INIT, "hw interface down");
|
||||
carp_set_state(sc, INIT, "hardware interface down");
|
||||
carp_setrun(sc, 0);
|
||||
if (!sc->sc_suppress)
|
||||
carp_demote_adj(V_carp_ifdown_adj, "interface down");
|
||||
sc->sc_suppress = 1;
|
||||
} else {
|
||||
carp_set_state(sc, INIT, "hw interface up");
|
||||
carp_set_state(sc, INIT, "hardware interface up");
|
||||
carp_setrun(sc, 0);
|
||||
if (sc->sc_suppress)
|
||||
carp_demote_adj(-V_carp_ifdown_adj, "interface up");
|
||||
|
@ -237,14 +237,14 @@ extern void *rfid_patch, *rfi_patch1, *rfi_patch2;
|
||||
extern void *trapcode64;
|
||||
#endif
|
||||
|
||||
extern void *rstcode, *rstsize;
|
||||
extern void *trapcode, *trapsize, *trapcode2;
|
||||
extern void *slbtrap, *slbtrapsize;
|
||||
extern void *alitrap, *alisize;
|
||||
extern void *dsitrap, *dsisize;
|
||||
extern void *rstcode, *rstcodeend;
|
||||
extern void *trapcode, *trapcodeend, *trapcode2;
|
||||
extern void *slbtrap, *slbtrapend;
|
||||
extern void *alitrap, *aliend;
|
||||
extern void *dsitrap, *dsiend;
|
||||
extern void *decrint, *decrsize;
|
||||
extern void *extint, *extsize;
|
||||
extern void *dblow, *dbsize;
|
||||
extern void *dblow, *dbend;
|
||||
extern void *imisstrap, *imisssize;
|
||||
extern void *dlmisstrap, *dlmisssize;
|
||||
extern void *dsmisstrap, *dsmisssize;
|
||||
@ -255,7 +255,7 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
|
||||
struct pcpu *pc;
|
||||
vm_offset_t startkernel, endkernel;
|
||||
void *generictrap;
|
||||
size_t trap_offset;
|
||||
size_t trap_offset, trapsize;
|
||||
void *kmdp;
|
||||
char *env;
|
||||
register_t msr, scratch;
|
||||
@ -513,35 +513,44 @@ powerpc_init(vm_offset_t fdt, vm_offset_t toc, vm_offset_t ofentry, void *mdp)
|
||||
*((register_t *)TRAP_TOCBASE) = toc;
|
||||
#endif
|
||||
|
||||
bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstsize);
|
||||
trapsize = (size_t)&trapcodeend - (size_t)&trapcode;
|
||||
|
||||
bcopy(&rstcode, (void *)(EXC_RST + trap_offset), (size_t)&rstcodeend -
|
||||
(size_t)&rstcode);
|
||||
|
||||
#ifdef KDB
|
||||
bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbsize);
|
||||
bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbsize);
|
||||
bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbsize);
|
||||
bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbsize);
|
||||
bcopy(&dblow, (void *)(EXC_MCHK + trap_offset), (size_t)&dbend -
|
||||
(size_t)&dblow);
|
||||
bcopy(&dblow, (void *)(EXC_PGM + trap_offset), (size_t)&dbend -
|
||||
(size_t)&dblow);
|
||||
bcopy(&dblow, (void *)(EXC_TRC + trap_offset), (size_t)&dbend -
|
||||
(size_t)&dblow);
|
||||
bcopy(&dblow, (void *)(EXC_BPT + trap_offset), (size_t)&dbend -
|
||||
(size_t)&dblow);
|
||||
#else
|
||||
bcopy(generictrap, (void *)EXC_MCHK, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_PGM, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_TRC, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_BPT, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_MCHK, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_PGM, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_TRC, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_BPT, trapsize);
|
||||
#endif
|
||||
bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&alisize);
|
||||
bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsisize);
|
||||
bcopy(generictrap, (void *)EXC_ISI, (size_t)&trapsize);
|
||||
bcopy(&alitrap, (void *)(EXC_ALI + trap_offset), (size_t)&aliend -
|
||||
(size_t)&alitrap);
|
||||
bcopy(&dsitrap, (void *)(EXC_DSI + trap_offset), (size_t)&dsiend -
|
||||
(size_t)&dsitrap);
|
||||
bcopy(generictrap, (void *)EXC_ISI, trapsize);
|
||||
#ifdef __powerpc64__
|
||||
bcopy(&slbtrap, (void *)EXC_DSE, (size_t)&slbtrapsize);
|
||||
bcopy(&slbtrap, (void *)EXC_ISE, (size_t)&slbtrapsize);
|
||||
bcopy(&slbtrap, (void *)EXC_DSE,(size_t)&slbtrapend - (size_t)&slbtrap);
|
||||
bcopy(&slbtrap, (void *)EXC_ISE,(size_t)&slbtrapend - (size_t)&slbtrap);
|
||||
#endif
|
||||
bcopy(generictrap, (void *)EXC_EXI, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_FPU, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_DECR, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_SC, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_FPA, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VEC, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_PERF, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VECAST_G4, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VECAST_G5, (size_t)&trapsize);
|
||||
bcopy(generictrap, (void *)EXC_EXI, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_FPU, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_DECR, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_SC, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_FPA, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VEC, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_PERF, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VECAST_G4, trapsize);
|
||||
bcopy(generictrap, (void *)EXC_VECAST_G5, trapsize);
|
||||
#ifndef __powerpc64__
|
||||
/* G2-specific TLB miss helper handlers */
|
||||
bcopy(&imisstrap, (void *)EXC_IMISS, (size_t)&imisssize);
|
||||
|
@ -299,10 +299,10 @@ CNAME(restorebridgesize) = .-CNAME(restorebridge)
|
||||
* not still hanging around in the trap handling region
|
||||
* once the MMU is turned on.
|
||||
*/
|
||||
.globl CNAME(rstcode), CNAME(rstsize)
|
||||
.globl CNAME(rstcode), CNAME(rstcodeend)
|
||||
CNAME(rstcode):
|
||||
ba cpu_reset
|
||||
CNAME(rstsize) = . - CNAME(rstcode)
|
||||
CNAME(rstcodeend):
|
||||
|
||||
cpu_reset:
|
||||
bl 1f
|
||||
@ -339,14 +339,14 @@ cpu_reset:
|
||||
* (except ISI/DSI, ALI, and the interrupts)
|
||||
*/
|
||||
|
||||
.globl CNAME(trapcode),CNAME(trapsize)
|
||||
.globl CNAME(trapcode),CNAME(trapcodeend)
|
||||
CNAME(trapcode):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
mflr %r1 /* Save the old LR in r1 */
|
||||
mtsprg2 %r1 /* And then in SPRG2 */
|
||||
li %r1, 0x20 /* How to get the vector from LR */
|
||||
bla generictrap /* LR & SPRG3 is exception # */
|
||||
CNAME(trapsize) = .-CNAME(trapcode)
|
||||
CNAME(trapcodeend):
|
||||
|
||||
/*
|
||||
* 64-bit version of trapcode. Identical, except it calls generictrap64.
|
||||
@ -362,7 +362,7 @@ CNAME(trapcode64):
|
||||
/*
|
||||
* For ALI: has to save DSISR and DAR
|
||||
*/
|
||||
.globl CNAME(alitrap),CNAME(alisize)
|
||||
.globl CNAME(alitrap),CNAME(aliend)
|
||||
CNAME(alitrap):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
GET_CPUINFO(%r1)
|
||||
@ -386,7 +386,7 @@ CNAME(alitrap):
|
||||
mfsrr1 %r31
|
||||
mtcr %r31
|
||||
bla s_trap
|
||||
CNAME(alisize) = .-CNAME(alitrap)
|
||||
CNAME(aliend):
|
||||
|
||||
/*
|
||||
* G2 specific: instuction TLB miss.
|
||||
@ -594,7 +594,7 @@ CNAME(dsmisssize) = .-CNAME(dsmisstrap)
|
||||
* Has to handle BAT spills
|
||||
* and standard pagetable spills
|
||||
*/
|
||||
.globl CNAME(dsitrap),CNAME(dsisize)
|
||||
.globl CNAME(dsitrap),CNAME(dsiend)
|
||||
CNAME(dsitrap):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
GET_CPUINFO(%r1)
|
||||
@ -645,7 +645,7 @@ CNAME(dsitrap):
|
||||
1:
|
||||
mflr %r28 /* save LR (SP already saved) */
|
||||
bla disitrap
|
||||
CNAME(dsisize) = .-CNAME(dsitrap)
|
||||
CNAME(dsiend):
|
||||
|
||||
/*
|
||||
* Preamble code for DSI/ISI traps
|
||||
@ -883,7 +883,7 @@ CNAME(rfi_patch2):
|
||||
/*
|
||||
* In case of KDB we want a separate trap catcher for it
|
||||
*/
|
||||
.globl CNAME(dblow),CNAME(dbsize)
|
||||
.globl CNAME(dblow),CNAME(dbend)
|
||||
CNAME(dblow):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
mtsprg2 %r29 /* save r29 */
|
||||
@ -909,5 +909,5 @@ CNAME(dblow):
|
||||
stw %r31,(PC_DBSAVE+CPUSAVE_R31)(%r1) /* free r31 */
|
||||
mflr %r28 /* save LR */
|
||||
bla dbtrap
|
||||
CNAME(dbsize) = .-CNAME(dblow)
|
||||
CNAME(dbend):
|
||||
#endif /* KDB */
|
||||
|
@ -294,7 +294,7 @@ dtrace_invop_calltrap_addr:
|
||||
* not still hanging around in the trap handling region
|
||||
* once the MMU is turned on.
|
||||
*/
|
||||
.globl CNAME(rstcode), CNAME(rstsize)
|
||||
.globl CNAME(rstcode), CNAME(rstcodeend)
|
||||
CNAME(rstcode):
|
||||
/* Explicitly set MSR[SF] */
|
||||
mfmsr %r9
|
||||
@ -309,7 +309,7 @@ CNAME(rstcode):
|
||||
mtlr %r9
|
||||
|
||||
blr
|
||||
CNAME(rstsize) = . - CNAME(rstcode)
|
||||
CNAME(rstcodeend):
|
||||
|
||||
cpu_reset:
|
||||
GET_TOCBASE(%r2)
|
||||
@ -350,7 +350,7 @@ cpu_reset:
|
||||
* (except ISI/DSI, ALI, and the interrupts). Has to fit in 8 instructions!
|
||||
*/
|
||||
|
||||
.globl CNAME(trapcode),CNAME(trapsize)
|
||||
.globl CNAME(trapcode),CNAME(trapcodeend)
|
||||
.p2align 3
|
||||
CNAME(trapcode):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
@ -361,7 +361,7 @@ CNAME(trapcode):
|
||||
mtlr %r1
|
||||
li %r1, 0xA0 /* How to get the vector from LR */
|
||||
blrl /* Branch to generictrap */
|
||||
CNAME(trapsize) = .-CNAME(trapcode)
|
||||
CNAME(trapcodeend):
|
||||
|
||||
/*
|
||||
* For SLB misses: do special things for the kernel
|
||||
@ -369,7 +369,7 @@ CNAME(trapsize) = .-CNAME(trapcode)
|
||||
* Note: SPRG1 is always safe to overwrite any time the MMU is on, which is
|
||||
* the only time this can be called.
|
||||
*/
|
||||
.globl CNAME(slbtrap),CNAME(slbtrapsize)
|
||||
.globl CNAME(slbtrap),CNAME(slbtrapend)
|
||||
.p2align 3
|
||||
CNAME(slbtrap):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
@ -404,7 +404,7 @@ CNAME(slbtrap):
|
||||
mtlr %r1
|
||||
GET_CPUINFO(%r1)
|
||||
blrl /* 124 bytes -- 4 to spare */
|
||||
CNAME(slbtrapsize) = .-CNAME(slbtrap)
|
||||
CNAME(slbtrapend):
|
||||
|
||||
kern_slbtrap:
|
||||
std %r2,(PC_SLBSAVE+136)(%r1) /* old LR */
|
||||
@ -525,7 +525,7 @@ kern_slbtrap:
|
||||
/*
|
||||
* For ALI: has to save DSISR and DAR
|
||||
*/
|
||||
.globl CNAME(alitrap),CNAME(alisize)
|
||||
.globl CNAME(alitrap),CNAME(aliend)
|
||||
CNAME(alitrap):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
GET_CPUINFO(%r1)
|
||||
@ -560,13 +560,13 @@ CNAME(alitrap):
|
||||
mfsrr1 %r31
|
||||
mtcr %r31
|
||||
blrl
|
||||
CNAME(alisize) = .-CNAME(alitrap)
|
||||
CNAME(aliend):
|
||||
|
||||
/*
|
||||
* Similar to the above for DSI
|
||||
* Has to handle standard pagetable spills
|
||||
*/
|
||||
.globl CNAME(dsitrap),CNAME(dsisize)
|
||||
.globl CNAME(dsitrap),CNAME(dsiend)
|
||||
CNAME(dsitrap):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
GET_CPUINFO(%r1)
|
||||
@ -587,7 +587,7 @@ CNAME(dsitrap):
|
||||
ld %r1,0(%r1)
|
||||
mtlr %r1
|
||||
blrl /* Branch to generictrap */
|
||||
CNAME(dsisize) = .-CNAME(dsitrap)
|
||||
CNAME(dsiend):
|
||||
|
||||
/*
|
||||
* Preamble code for DSI/ISI traps
|
||||
@ -830,7 +830,7 @@ dbleave:
|
||||
/*
|
||||
* In case of KDB we want a separate trap catcher for it
|
||||
*/
|
||||
.globl CNAME(dblow),CNAME(dbsize)
|
||||
.globl CNAME(dblow),CNAME(dbend)
|
||||
CNAME(dblow):
|
||||
mtsprg1 %r1 /* save SP */
|
||||
mtsprg2 %r29 /* save r29 */
|
||||
@ -869,5 +869,5 @@ CNAME(dblow):
|
||||
ld %r1,0(%r1)
|
||||
mtlr %r1
|
||||
blrl /* Branch to generictrap */
|
||||
CNAME(dbsize) = .-CNAME(dblow)
|
||||
CNAME(dbend):
|
||||
#endif /* KDB */
|
||||
|
@ -99,8 +99,6 @@ memrw(struct cdev *dev, struct uio *uio, int flags)
|
||||
error = 0;
|
||||
ova = 0;
|
||||
|
||||
GIANT_REQUIRED;
|
||||
|
||||
while (uio->uio_resid > 0 && error == 0) {
|
||||
iov = uio->uio_iov;
|
||||
if (iov->iov_len == 0) {
|
||||
|
@ -146,9 +146,9 @@
|
||||
#define CAP_FSTATAT (CAP_FSTAT | CAP_LOOKUP)
|
||||
/* Allows for fstatfs(2). */
|
||||
#define CAP_FSTATFS CAPRIGHT(0, 0x0000000000100000ULL)
|
||||
/* Allows for futimes(2). */
|
||||
/* Allows for futimens(2) and futimes(2). */
|
||||
#define CAP_FUTIMES CAPRIGHT(0, 0x0000000000200000ULL)
|
||||
/* Allows for futimes(2) and futimesat(2). */
|
||||
/* Allows for futimens(2), futimes(2), futimesat(2) and utimensat(2). */
|
||||
#define CAP_FUTIMESAT (CAP_FUTIMES | CAP_LOOKUP)
|
||||
/* Allows for linkat(2) and renameat(2) (destination directory descriptor). */
|
||||
#define CAP_LINKAT (CAP_LOOKUP | 0x0000000000400000ULL)
|
||||
|
@ -58,7 +58,7 @@
|
||||
* in the range 5 to 9.
|
||||
*/
|
||||
#undef __FreeBSD_version
|
||||
#define __FreeBSD_version 1100055 /* Master, propagated to newvers */
|
||||
#define __FreeBSD_version 1100056 /* Master, propagated to newvers */
|
||||
|
||||
/*
|
||||
* __FreeBSD_kernel__ indicates that this system uses the kernel of FreeBSD,
|
||||
|
@ -307,6 +307,11 @@ struct nstat {
|
||||
|
||||
#endif /* __BSD_VISIBLE */
|
||||
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
#define UTIME_NOW -1
|
||||
#define UTIME_OMIT -2
|
||||
#endif
|
||||
|
||||
#ifndef _KERNEL
|
||||
__BEGIN_DECLS
|
||||
#if __BSD_VISIBLE
|
||||
@ -322,6 +327,9 @@ int fchmod(int, mode_t);
|
||||
#endif
|
||||
#if __POSIX_VISIBLE >= 200809
|
||||
int fchmodat(int, const char *, mode_t, int);
|
||||
int futimens(int fd, const struct timespec times[2]);
|
||||
int utimensat(int fd, const char *path, const struct timespec times[2],
|
||||
int flag);
|
||||
#endif
|
||||
int fstat(int, struct stat *);
|
||||
#if __BSD_VISIBLE
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#define SYS_syscall 0
|
||||
@ -463,4 +463,6 @@
|
||||
#define SYS_aio_mlock 543
|
||||
#define SYS_procctl 544
|
||||
#define SYS_ppoll 545
|
||||
#define SYS_MAXSYSCALL 546
|
||||
#define SYS_futimens 546
|
||||
#define SYS_utimensat 547
|
||||
#define SYS_MAXSYSCALL 548
|
||||
|
@ -1,7 +1,7 @@
|
||||
# FreeBSD system call names.
|
||||
# DO NOT EDIT-- this file is automatically generated.
|
||||
# $FreeBSD$
|
||||
# created from FreeBSD: head/sys/kern/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
# created from FreeBSD: head/sys/kern/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
MIASM = \
|
||||
syscall.o \
|
||||
exit.o \
|
||||
@ -410,4 +410,6 @@ MIASM = \
|
||||
pipe2.o \
|
||||
aio_mlock.o \
|
||||
procctl.o \
|
||||
ppoll.o
|
||||
ppoll.o \
|
||||
futimens.o \
|
||||
utimensat.o
|
||||
|
@ -99,6 +99,8 @@ int kern_fstatfs(struct thread *td, int fd, struct statfs *buf);
|
||||
int kern_ftruncate(struct thread *td, int fd, off_t length);
|
||||
int kern_futimes(struct thread *td, int fd, struct timeval *tptr,
|
||||
enum uio_seg tptrseg);
|
||||
int kern_futimens(struct thread *td, int fd, struct timespec *tptr,
|
||||
enum uio_seg tptrseg);
|
||||
int kern_getdirentries(struct thread *td, int fd, char *buf, u_int count,
|
||||
long *basep, ssize_t *residp, enum uio_seg bufseg);
|
||||
int kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize,
|
||||
@ -220,6 +222,9 @@ int kern_unlinkat(struct thread *td, int fd, char *path,
|
||||
enum uio_seg pathseg, ino_t oldinum);
|
||||
int kern_utimesat(struct thread *td, int fd, char *path,
|
||||
enum uio_seg pathseg, struct timeval *tptr, enum uio_seg tptrseg);
|
||||
int kern_utimensat(struct thread *td, int fd, char *path,
|
||||
enum uio_seg pathseg, struct timespec *tptr, enum uio_seg tptrseg,
|
||||
int follow);
|
||||
int kern_wait(struct thread *td, pid_t pid, int *status, int options,
|
||||
struct rusage *rup);
|
||||
int kern_wait6(struct thread *td, enum idtype idtype, id_t id, int *status,
|
||||
|
@ -3,7 +3,7 @@
|
||||
*
|
||||
* DO NOT EDIT-- this file is automatically generated.
|
||||
* $FreeBSD$
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 276654 2015-01-04 10:34:02Z dchagin
|
||||
* created from FreeBSD: head/sys/kern/syscalls.master 277610 2015-01-23 21:07:08Z jilles
|
||||
*/
|
||||
|
||||
#ifndef _SYS_SYSPROTO_H_
|
||||
@ -1819,6 +1819,16 @@ struct ppoll_args {
|
||||
char ts_l_[PADL_(const struct timespec *)]; const struct timespec * ts; char ts_r_[PADR_(const struct timespec *)];
|
||||
char set_l_[PADL_(const sigset_t *)]; const sigset_t * set; char set_r_[PADR_(const sigset_t *)];
|
||||
};
|
||||
struct futimens_args {
|
||||
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
|
||||
char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)];
|
||||
};
|
||||
struct utimensat_args {
|
||||
char fd_l_[PADL_(int)]; int fd; char fd_r_[PADR_(int)];
|
||||
char path_l_[PADL_(char *)]; char * path; char path_r_[PADR_(char *)];
|
||||
char times_l_[PADL_(struct timespec *)]; struct timespec * times; char times_r_[PADR_(struct timespec *)];
|
||||
char flag_l_[PADL_(int)]; int flag; char flag_r_[PADR_(int)];
|
||||
};
|
||||
int nosys(struct thread *, struct nosys_args *);
|
||||
void sys_sys_exit(struct thread *, struct sys_exit_args *);
|
||||
int sys_fork(struct thread *, struct fork_args *);
|
||||
@ -2211,6 +2221,8 @@ int sys_pipe2(struct thread *, struct pipe2_args *);
|
||||
int sys_aio_mlock(struct thread *, struct aio_mlock_args *);
|
||||
int sys_procctl(struct thread *, struct procctl_args *);
|
||||
int sys_ppoll(struct thread *, struct ppoll_args *);
|
||||
int sys_futimens(struct thread *, struct futimens_args *);
|
||||
int sys_utimensat(struct thread *, struct utimensat_args *);
|
||||
|
||||
#ifdef COMPAT_43
|
||||
|
||||
@ -2917,6 +2929,8 @@ int freebsd7_shmctl(struct thread *, struct freebsd7_shmctl_args *);
|
||||
#define SYS_AUE_aio_mlock AUE_NULL
|
||||
#define SYS_AUE_procctl AUE_NULL
|
||||
#define SYS_AUE_ppoll AUE_POLL
|
||||
#define SYS_AUE_futimens AUE_FUTIMES
|
||||
#define SYS_AUE_utimensat AUE_FUTIMESAT
|
||||
|
||||
#undef PAD_
|
||||
#undef PADL_
|
||||
|
@ -383,16 +383,33 @@ struct { \
|
||||
#define RB_PROTOTYPE_STATIC(name, type, field, cmp) \
|
||||
RB_PROTOTYPE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_PROTOTYPE_INTERNAL(name, type, field, cmp, attr) \
|
||||
attr void name##_RB_INSERT_COLOR(struct name *, struct type *); \
|
||||
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *);\
|
||||
attr struct type *name##_RB_REMOVE(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_INSERT(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *); \
|
||||
attr struct type *name##_RB_NEXT(struct type *); \
|
||||
attr struct type *name##_RB_PREV(struct type *); \
|
||||
attr struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
\
|
||||
RB_PROTOTYPE_INSERT_COLOR(name, type, attr); \
|
||||
RB_PROTOTYPE_REMOVE_COLOR(name, type, attr); \
|
||||
RB_PROTOTYPE_INSERT(name, type, attr); \
|
||||
RB_PROTOTYPE_REMOVE(name, type, attr); \
|
||||
RB_PROTOTYPE_FIND(name, type, attr); \
|
||||
RB_PROTOTYPE_NFIND(name, type, attr); \
|
||||
RB_PROTOTYPE_NEXT(name, type, attr); \
|
||||
RB_PROTOTYPE_PREV(name, type, attr); \
|
||||
RB_PROTOTYPE_MINMAX(name, type, attr);
|
||||
#define RB_PROTOTYPE_INSERT_COLOR(name, type, attr) \
|
||||
attr void name##_RB_INSERT_COLOR(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_REMOVE_COLOR(name, type, attr) \
|
||||
attr void name##_RB_REMOVE_COLOR(struct name *, struct type *, struct type *)
|
||||
#define RB_PROTOTYPE_REMOVE(name, type, attr) \
|
||||
attr struct type *name##_RB_REMOVE(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_INSERT(name, type, attr) \
|
||||
attr struct type *name##_RB_INSERT(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_FIND(name, type, attr) \
|
||||
attr struct type *name##_RB_FIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_NFIND(name, type, attr) \
|
||||
attr struct type *name##_RB_NFIND(struct name *, struct type *)
|
||||
#define RB_PROTOTYPE_NEXT(name, type, attr) \
|
||||
attr struct type *name##_RB_NEXT(struct type *)
|
||||
#define RB_PROTOTYPE_PREV(name, type, attr) \
|
||||
attr struct type *name##_RB_PREV(struct type *)
|
||||
#define RB_PROTOTYPE_MINMAX(name, type, attr) \
|
||||
attr struct type *name##_RB_MINMAX(struct name *, int)
|
||||
|
||||
/* Main rb operation.
|
||||
* Moves node close to the key of elm to top
|
||||
@ -402,6 +419,17 @@ attr struct type *name##_RB_MINMAX(struct name *, int); \
|
||||
#define RB_GENERATE_STATIC(name, type, field, cmp) \
|
||||
RB_GENERATE_INTERNAL(name, type, field, cmp, __unused static)
|
||||
#define RB_GENERATE_INTERNAL(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
|
||||
RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
|
||||
RB_GENERATE_INSERT(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_REMOVE(name, type, field, attr) \
|
||||
RB_GENERATE_FIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_NFIND(name, type, field, cmp, attr) \
|
||||
RB_GENERATE_NEXT(name, type, field, attr) \
|
||||
RB_GENERATE_PREV(name, type, field, attr) \
|
||||
RB_GENERATE_MINMAX(name, type, field, attr)
|
||||
|
||||
#define RB_GENERATE_INSERT_COLOR(name, type, field, attr) \
|
||||
attr void \
|
||||
name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
@ -444,8 +472,9 @@ name##_RB_INSERT_COLOR(struct name *head, struct type *elm) \
|
||||
} \
|
||||
} \
|
||||
RB_COLOR(head->rbh_root, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_REMOVE_COLOR(name, type, field, attr) \
|
||||
attr void \
|
||||
name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm) \
|
||||
{ \
|
||||
@ -522,8 +551,9 @@ name##_RB_REMOVE_COLOR(struct name *head, struct type *parent, struct type *elm)
|
||||
} \
|
||||
if (elm) \
|
||||
RB_COLOR(elm, field) = RB_BLACK; \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_REMOVE(name, type, field, attr) \
|
||||
attr struct type * \
|
||||
name##_RB_REMOVE(struct name *head, struct type *elm) \
|
||||
{ \
|
||||
@ -590,7 +620,8 @@ color: \
|
||||
name##_RB_REMOVE_COLOR(head, parent, child); \
|
||||
return (old); \
|
||||
} \
|
||||
\
|
||||
|
||||
#define RB_GENERATE_INSERT(name, type, field, cmp, attr) \
|
||||
/* Inserts a node into the RB tree */ \
|
||||
attr struct type * \
|
||||
name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
@ -620,8 +651,9 @@ name##_RB_INSERT(struct name *head, struct type *elm) \
|
||||
RB_ROOT(head) = elm; \
|
||||
name##_RB_INSERT_COLOR(head, elm); \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_FIND(name, type, field, cmp, attr) \
|
||||
/* Finds the node with the same key as elm */ \
|
||||
attr struct type * \
|
||||
name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
@ -638,8 +670,9 @@ name##_RB_FIND(struct name *head, struct type *elm) \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (NULL); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NFIND(name, type, field, cmp, attr) \
|
||||
/* Finds the first node greater than or equal to the search key */ \
|
||||
attr struct type * \
|
||||
name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
@ -659,8 +692,9 @@ name##_RB_NFIND(struct name *head, struct type *elm) \
|
||||
return (tmp); \
|
||||
} \
|
||||
return (res); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_NEXT(name, type, field, attr) \
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_NEXT(struct type *elm) \
|
||||
@ -681,8 +715,9 @@ name##_RB_NEXT(struct type *elm) \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_PREV(name, type, field, attr) \
|
||||
/* ARGSUSED */ \
|
||||
attr struct type * \
|
||||
name##_RB_PREV(struct type *elm) \
|
||||
@ -703,8 +738,9 @@ name##_RB_PREV(struct type *elm) \
|
||||
} \
|
||||
} \
|
||||
return (elm); \
|
||||
} \
|
||||
\
|
||||
}
|
||||
|
||||
#define RB_GENERATE_MINMAX(name, type, field, attr) \
|
||||
attr struct type * \
|
||||
name##_RB_MINMAX(struct name *head, int val) \
|
||||
{ \
|
||||
|
@ -344,6 +344,9 @@ void
|
||||
vmspace_free(struct vmspace *vm)
|
||||
{
|
||||
|
||||
WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
|
||||
"vmspace_free() called with non-sleepable lock held");
|
||||
|
||||
if (vm->vm_refcnt == 0)
|
||||
panic("vmspace_free: attempt to free already freed vmspace");
|
||||
|
||||
|
@ -180,6 +180,12 @@ static int vm_swap_enabled = 1;
|
||||
static int vm_swap_idle_enabled = 0;
|
||||
#endif
|
||||
|
||||
static int vm_panic_on_oom = 0;
|
||||
|
||||
SYSCTL_INT(_vm, OID_AUTO, panic_on_oom,
|
||||
CTLFLAG_RWTUN, &vm_panic_on_oom, 0,
|
||||
"panic on out of memory instead of killing the largest process");
|
||||
|
||||
SYSCTL_INT(_vm, OID_AUTO, pageout_wakeup_thresh,
|
||||
CTLFLAG_RW, &vm_pageout_wakeup_thresh, 0,
|
||||
"free page threshold for waking up the pageout daemon");
|
||||
@ -1516,15 +1522,15 @@ vm_pageout_oom(int shortage)
|
||||
FOREACH_PROC_IN_SYSTEM(p) {
|
||||
int breakout;
|
||||
|
||||
if (PROC_TRYLOCK(p) == 0)
|
||||
continue;
|
||||
PROC_LOCK(p);
|
||||
|
||||
/*
|
||||
* If this is a system, protected or killed process, skip it.
|
||||
*/
|
||||
if (p->p_state != PRS_NORMAL ||
|
||||
(p->p_flag & (P_INEXEC | P_PROTECTED | P_SYSTEM)) ||
|
||||
(p->p_pid == 1) || P_KILLED(p) ||
|
||||
((p->p_pid < 48) && (swap_pager_avail != 0))) {
|
||||
if (p->p_state != PRS_NORMAL || (p->p_flag & (P_INEXEC |
|
||||
P_PROTECTED | P_SYSTEM | P_WEXIT)) != 0 ||
|
||||
p->p_pid == 1 || P_KILLED(p) ||
|
||||
(p->p_pid < 48 && swap_pager_avail != 0)) {
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
@ -1557,11 +1563,14 @@ vm_pageout_oom(int shortage)
|
||||
PROC_UNLOCK(p);
|
||||
continue;
|
||||
}
|
||||
_PHOLD(p);
|
||||
if (!vm_map_trylock_read(&vm->vm_map)) {
|
||||
vmspace_free(vm);
|
||||
_PRELE(p);
|
||||
PROC_UNLOCK(p);
|
||||
vmspace_free(vm);
|
||||
continue;
|
||||
}
|
||||
PROC_UNLOCK(p);
|
||||
size = vmspace_swap_count(vm);
|
||||
vm_map_unlock_read(&vm->vm_map);
|
||||
if (shortage == VM_OOM_MEM)
|
||||
@ -1573,16 +1582,21 @@ vm_pageout_oom(int shortage)
|
||||
*/
|
||||
if (size > bigsize) {
|
||||
if (bigproc != NULL)
|
||||
PROC_UNLOCK(bigproc);
|
||||
PRELE(bigproc);
|
||||
bigproc = p;
|
||||
bigsize = size;
|
||||
} else
|
||||
PROC_UNLOCK(p);
|
||||
} else {
|
||||
PRELE(p);
|
||||
}
|
||||
}
|
||||
sx_sunlock(&allproc_lock);
|
||||
if (bigproc != NULL) {
|
||||
if (vm_panic_on_oom != 0)
|
||||
panic("out of swap space");
|
||||
PROC_LOCK(bigproc);
|
||||
killproc(bigproc, "out of swap space");
|
||||
sched_nice(bigproc, PRIO_MIN);
|
||||
_PRELE(bigproc);
|
||||
PROC_UNLOCK(bigproc);
|
||||
wakeup(&vm_cnt.v_free_count);
|
||||
}
|
||||
|
@ -36,6 +36,7 @@
|
||||
#include <sys/stat.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <assert.h>
|
||||
#include <err.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
@ -48,9 +49,7 @@
|
||||
#include <unistd.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#if __FreeBSD_version >= 800028
|
||||
#define HAVE_SYSID
|
||||
#endif
|
||||
#include <sys/cdefs.h>
|
||||
#else
|
||||
#ifndef nitems
|
||||
@ -72,8 +71,6 @@ static int
|
||||
make_file(const char *pathname, off_t sz)
|
||||
{
|
||||
struct stat st;
|
||||
const char *template = "/flocktempXXXXXX";
|
||||
size_t len;
|
||||
char *filename;
|
||||
int fd;
|
||||
|
||||
@ -88,10 +85,8 @@ make_file(const char *pathname, off_t sz)
|
||||
}
|
||||
}
|
||||
|
||||
len = strlen(pathname) + strlen(template) + 1;
|
||||
filename = malloc(len);
|
||||
strcpy(filename, pathname);
|
||||
strcat(filename, template);
|
||||
if (asprintf(&filename, "%s/flocktempXXXXXX", pathname) == -1)
|
||||
err(1, "asprintf");
|
||||
fd = mkstemp(filename);
|
||||
if (fd < 0)
|
||||
err(1, "mkstemp");
|
||||
@ -127,12 +122,12 @@ safe_waitpid(pid_t pid)
|
||||
return (status);
|
||||
}
|
||||
|
||||
#define FAIL(test) \
|
||||
do { \
|
||||
if (test) { \
|
||||
printf("FAIL (%s)\n", #test); \
|
||||
return -1; \
|
||||
} \
|
||||
#define FAIL(test) \
|
||||
do { \
|
||||
if (test) { \
|
||||
printf("FAIL @ %d (%s)\n", __LINE__, #test); \
|
||||
assert(0); \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#define SUCCEED \
|
||||
@ -1575,18 +1570,6 @@ main(int argc, const char *argv[])
|
||||
sigaction(SIGALRM, &sa, 0);
|
||||
|
||||
nointr = 0;
|
||||
#if defined(__FreeBSD__) && __FreeBSD_version < 800040
|
||||
{
|
||||
/*
|
||||
* FreeBSD with userland NLM can't interrupt a blocked
|
||||
* lock request on an NFS mounted filesystem.
|
||||
*/
|
||||
struct statfs st;
|
||||
fstatfs(fd, &st);
|
||||
nointr = !strcmp(st.f_fstypename, "nfs");
|
||||
}
|
||||
#endif
|
||||
|
||||
for (i = 0; i < nitems(tests); i++) {
|
||||
if (tests[i].intr && nointr)
|
||||
continue;
|
||||
|
@ -714,6 +714,7 @@ ktrsyscall(struct ktr_syscall *ktr, u_int flags)
|
||||
case SYS_readlinkat:
|
||||
case SYS_renameat:
|
||||
case SYS_unlinkat:
|
||||
case SYS_utimensat:
|
||||
putchar('(');
|
||||
atfdname(*ip, decimal);
|
||||
c = ',';
|
||||
|
@ -56,10 +56,10 @@ static const char sccsid[] = "@(#)touch.c 8.1 (Berkeley) 6/6/93";
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
|
||||
static void stime_arg1(const char *, struct timeval *);
|
||||
static void stime_arg2(const char *, int, struct timeval *);
|
||||
static void stime_darg(const char *, struct timeval *);
|
||||
static void stime_file(const char *, struct timeval *);
|
||||
static void stime_arg1(const char *, struct timespec *);
|
||||
static void stime_arg2(const char *, int, struct timespec *);
|
||||
static void stime_darg(const char *, struct timespec *);
|
||||
static void stime_file(const char *, struct timespec *);
|
||||
static int timeoffset(const char *);
|
||||
static void usage(const char *);
|
||||
|
||||
@ -67,19 +67,17 @@ int
|
||||
main(int argc, char *argv[])
|
||||
{
|
||||
struct stat sb;
|
||||
struct timeval tv[2];
|
||||
int (*stat_f)(const char *, struct stat *);
|
||||
int (*utimes_f)(const char *, const struct timeval *);
|
||||
struct timespec ts[2];
|
||||
int atflag;
|
||||
int Aflag, aflag, cflag, mflag, ch, fd, len, rval, timeset;
|
||||
char *p;
|
||||
char *myname;
|
||||
|
||||
myname = basename(argv[0]);
|
||||
Aflag = aflag = cflag = mflag = timeset = 0;
|
||||
stat_f = stat;
|
||||
utimes_f = utimes;
|
||||
if (gettimeofday(&tv[0], NULL) == -1)
|
||||
err(1, "gettimeofday");
|
||||
atflag = 0;
|
||||
if (clock_gettime(CLOCK_REALTIME, &ts[0]) == -1)
|
||||
err(1, "clock_gettime(CLOCK_REALTIME)");
|
||||
|
||||
while ((ch = getopt(argc, argv, "A:acd:fhmr:t:")) != -1)
|
||||
switch(ch) {
|
||||
@ -94,26 +92,25 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'd':
|
||||
timeset = 1;
|
||||
stime_darg(optarg, tv);
|
||||
stime_darg(optarg, ts);
|
||||
break;
|
||||
case 'f':
|
||||
/* No-op for compatibility. */
|
||||
break;
|
||||
case 'h':
|
||||
cflag = 1;
|
||||
stat_f = lstat;
|
||||
utimes_f = lutimes;
|
||||
atflag = AT_SYMLINK_NOFOLLOW;
|
||||
break;
|
||||
case 'm':
|
||||
mflag = 1;
|
||||
break;
|
||||
case 'r':
|
||||
timeset = 1;
|
||||
stime_file(optarg, tv);
|
||||
stime_file(optarg, ts);
|
||||
break;
|
||||
case 't':
|
||||
timeset = 1;
|
||||
stime_arg1(optarg, tv);
|
||||
stime_arg1(optarg, ts);
|
||||
break;
|
||||
default:
|
||||
usage(myname);
|
||||
@ -132,9 +129,9 @@ main(int argc, char *argv[])
|
||||
* that time once and for all here.
|
||||
*/
|
||||
if (aflag)
|
||||
tv[0].tv_sec += Aflag;
|
||||
ts[0].tv_sec += Aflag;
|
||||
if (mflag)
|
||||
tv[1].tv_sec += Aflag;
|
||||
ts[1].tv_sec += Aflag;
|
||||
Aflag = 0; /* done our job */
|
||||
}
|
||||
} else {
|
||||
@ -148,11 +145,11 @@ main(int argc, char *argv[])
|
||||
len = p - argv[0];
|
||||
if (*p == '\0' && (len == 8 || len == 10)) {
|
||||
timeset = 1;
|
||||
stime_arg2(*argv++, len == 10, tv);
|
||||
stime_arg2(*argv++, len == 10, ts);
|
||||
}
|
||||
}
|
||||
/* Both times default to the same. */
|
||||
tv[1] = tv[0];
|
||||
ts[1] = ts[0];
|
||||
}
|
||||
|
||||
if (*argv == NULL)
|
||||
@ -163,7 +160,7 @@ main(int argc, char *argv[])
|
||||
|
||||
for (rval = 0; *argv; ++argv) {
|
||||
/* See if the file exists. */
|
||||
if (stat_f(*argv, &sb) != 0) {
|
||||
if (fstatat(AT_FDCWD, *argv, &sb, atflag) != 0) {
|
||||
if (errno != ENOENT) {
|
||||
rval = 1;
|
||||
warn("%s", *argv);
|
||||
@ -187,9 +184,9 @@ main(int argc, char *argv[])
|
||||
}
|
||||
|
||||
if (!aflag)
|
||||
TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atim);
|
||||
ts[0] = sb.st_atim;
|
||||
if (!mflag)
|
||||
TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtim);
|
||||
ts[1] = sb.st_mtim;
|
||||
|
||||
/*
|
||||
* We're adjusting the times based on the file times, not a
|
||||
@ -197,17 +194,17 @@ main(int argc, char *argv[])
|
||||
*/
|
||||
if (Aflag) {
|
||||
if (aflag) {
|
||||
TIMESPEC_TO_TIMEVAL(&tv[0], &sb.st_atim);
|
||||
tv[0].tv_sec += Aflag;
|
||||
ts[0] = sb.st_atim;
|
||||
ts[0].tv_sec += Aflag;
|
||||
}
|
||||
if (mflag) {
|
||||
TIMESPEC_TO_TIMEVAL(&tv[1], &sb.st_mtim);
|
||||
tv[1].tv_sec += Aflag;
|
||||
ts[1] = sb.st_mtim;
|
||||
ts[1].tv_sec += Aflag;
|
||||
}
|
||||
}
|
||||
|
||||
/* Try utimes(2). */
|
||||
if (!utimes_f(*argv, tv))
|
||||
/* Try utimensat(2). */
|
||||
if (!utimensat(AT_FDCWD, *argv, ts, atflag))
|
||||
continue;
|
||||
|
||||
/* If the user specified a time, nothing else we can do. */
|
||||
@ -223,7 +220,7 @@ main(int argc, char *argv[])
|
||||
* The permission checks are different, too, in that the
|
||||
* ability to write the file is sufficient. Take a shot.
|
||||
*/
|
||||
if (!utimes_f(*argv, NULL))
|
||||
if (!utimensat(AT_FDCWD, *argv, NULL, atflag))
|
||||
continue;
|
||||
|
||||
rval = 1;
|
||||
@ -235,7 +232,7 @@ main(int argc, char *argv[])
|
||||
#define ATOI2(ar) ((ar)[0] - '0') * 10 + ((ar)[1] - '0'); (ar) += 2;
|
||||
|
||||
static void
|
||||
stime_arg1(const char *arg, struct timeval *tvp)
|
||||
stime_arg1(const char *arg, struct timespec *tvp)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
@ -291,7 +288,7 @@ stime_arg1(const char *arg, struct timeval *tvp)
|
||||
if (tvp[0].tv_sec == -1)
|
||||
goto terr;
|
||||
|
||||
tvp[0].tv_usec = tvp[1].tv_usec = 0;
|
||||
tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
|
||||
return;
|
||||
|
||||
terr:
|
||||
@ -299,7 +296,7 @@ stime_arg1(const char *arg, struct timeval *tvp)
|
||||
}
|
||||
|
||||
static void
|
||||
stime_arg2(const char *arg, int year, struct timeval *tvp)
|
||||
stime_arg2(const char *arg, int year, struct timespec *tvp)
|
||||
{
|
||||
time_t now;
|
||||
struct tm *t;
|
||||
@ -325,18 +322,18 @@ stime_arg2(const char *arg, int year, struct timeval *tvp)
|
||||
errx(1,
|
||||
"out of range or illegal time specification: MMDDhhmm[yy]");
|
||||
|
||||
tvp[0].tv_usec = tvp[1].tv_usec = 0;
|
||||
tvp[0].tv_nsec = tvp[1].tv_nsec = 0;
|
||||
}
|
||||
|
||||
static void
|
||||
stime_darg(const char *arg, struct timeval *tvp)
|
||||
stime_darg(const char *arg, struct timespec *tvp)
|
||||
{
|
||||
struct tm t = { .tm_sec = 0 };
|
||||
const char *fmt, *colon;
|
||||
char *p;
|
||||
int val, isutc = 0;
|
||||
|
||||
tvp[0].tv_usec = 0;
|
||||
tvp[0].tv_nsec = 0;
|
||||
t.tm_isdst = -1;
|
||||
colon = strchr(arg, ':');
|
||||
if (colon == NULL || strchr(colon + 1, ':') == NULL)
|
||||
@ -349,9 +346,9 @@ stime_darg(const char *arg, struct timeval *tvp)
|
||||
/* POSIX: must have at least one digit after dot */
|
||||
if ((*p == '.' || *p == ',') && isdigit((unsigned char)p[1])) {
|
||||
p++;
|
||||
val = 100000;
|
||||
val = 100000000;
|
||||
while (isdigit((unsigned char)*p)) {
|
||||
tvp[0].tv_usec += val * (*p - '0');
|
||||
tvp[0].tv_nsec += val * (*p - '0');
|
||||
p++;
|
||||
val /= 10;
|
||||
}
|
||||
@ -403,14 +400,14 @@ timeoffset(const char *arg)
|
||||
}
|
||||
|
||||
static void
|
||||
stime_file(const char *fname, struct timeval *tvp)
|
||||
stime_file(const char *fname, struct timespec *tsp)
|
||||
{
|
||||
struct stat sb;
|
||||
|
||||
if (stat(fname, &sb))
|
||||
err(1, "%s", fname);
|
||||
TIMESPEC_TO_TIMEVAL(tvp, &sb.st_atim);
|
||||
TIMESPEC_TO_TIMEVAL(tvp + 1, &sb.st_mtim);
|
||||
tsp[0] = sb.st_atim;
|
||||
tsp[1] = sb.st_mtim;
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -148,7 +148,7 @@ static void cpustats(void);
|
||||
static void pcpustats(int, u_long, int);
|
||||
static void devstats(void);
|
||||
static void doforkst(void);
|
||||
static void dointr(void);
|
||||
static void dointr(unsigned int, int);
|
||||
static void dosum(void);
|
||||
static void dovmstat(unsigned int, int);
|
||||
static void domemstat_malloc(void);
|
||||
@ -163,7 +163,7 @@ static void printhdr(int, u_long);
|
||||
static void usage(void);
|
||||
|
||||
static long pct(long, long);
|
||||
static long getuptime(void);
|
||||
static long long getuptime(void);
|
||||
|
||||
static char **getdrivedata(char **);
|
||||
|
||||
@ -325,7 +325,7 @@ main(int argc, char *argv[])
|
||||
dotimes();
|
||||
#endif
|
||||
if (todo & INTRSTAT)
|
||||
dointr();
|
||||
dointr(interval, reps);
|
||||
if (todo & VMSTAT)
|
||||
dovmstat(interval, reps);
|
||||
exit(0);
|
||||
@ -406,14 +406,15 @@ getdrivedata(char **argv)
|
||||
return(argv);
|
||||
}
|
||||
|
||||
static long
|
||||
/* Return system uptime in nanoseconds */
|
||||
static long long
|
||||
getuptime(void)
|
||||
{
|
||||
struct timespec sp;
|
||||
|
||||
(void)clock_gettime(CLOCK_MONOTONIC, &sp);
|
||||
(void)clock_gettime(CLOCK_UPTIME, &sp);
|
||||
|
||||
return(sp.tv_sec);
|
||||
return((long long)sp.tv_sec * 1000000000LL + sp.tv_nsec);
|
||||
}
|
||||
|
||||
static void
|
||||
@ -654,7 +655,7 @@ dovmstat(unsigned int interval, int reps)
|
||||
u_long cpumask;
|
||||
int rate_adj;
|
||||
|
||||
uptime = getuptime();
|
||||
uptime = getuptime() / 1000000000LL;
|
||||
halfuptime = uptime / 2;
|
||||
rate_adj = 1;
|
||||
ncpus = 1;
|
||||
@ -1165,61 +1166,133 @@ pcpustats(int ncpus, u_long cpumask, int maxid)
|
||||
}
|
||||
}
|
||||
|
||||
static void
|
||||
dointr(void)
|
||||
static unsigned int
|
||||
read_intrcnts(unsigned long **intrcnts)
|
||||
{
|
||||
unsigned long *intrcnt, uptime;
|
||||
uint64_t inttotal;
|
||||
size_t clen, inamlen, intrcntlen, istrnamlen;
|
||||
unsigned int i, nintr;
|
||||
char *intrname, *tintrname;
|
||||
size_t intrcntlen;
|
||||
|
||||
uptime = getuptime();
|
||||
if (kd != NULL) {
|
||||
kread(X_SINTRCNT, &intrcntlen, sizeof(intrcntlen));
|
||||
kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
|
||||
if ((intrcnt = malloc(intrcntlen)) == NULL ||
|
||||
(intrname = malloc(inamlen)) == NULL)
|
||||
if ((*intrcnts = malloc(intrcntlen)) == NULL)
|
||||
err(1, "malloc()");
|
||||
kread(X_INTRCNT, intrcnt, intrcntlen);
|
||||
kread(X_INTRNAMES, intrname, inamlen);
|
||||
kread(X_INTRCNT, *intrcnts, intrcntlen);
|
||||
} else {
|
||||
for (intrcnt = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
|
||||
if ((intrcnt = reallocf(intrcnt, intrcntlen)) == NULL)
|
||||
for (*intrcnts = NULL, intrcntlen = 1024; ; intrcntlen *= 2) {
|
||||
*intrcnts = reallocf(*intrcnts, intrcntlen);
|
||||
if (*intrcnts == NULL)
|
||||
err(1, "reallocf()");
|
||||
if (mysysctl("hw.intrcnt",
|
||||
intrcnt, &intrcntlen, NULL, 0) == 0)
|
||||
break;
|
||||
}
|
||||
for (intrname = NULL, inamlen = 1024; ; inamlen *= 2) {
|
||||
if ((intrname = reallocf(intrname, inamlen)) == NULL)
|
||||
err(1, "reallocf()");
|
||||
if (mysysctl("hw.intrnames",
|
||||
intrname, &inamlen, NULL, 0) == 0)
|
||||
*intrcnts, &intrcntlen, NULL, 0) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
nintr = intrcntlen / sizeof(unsigned long);
|
||||
tintrname = intrname;
|
||||
|
||||
return (intrcntlen / sizeof(unsigned long));
|
||||
}
|
||||
|
||||
static void
|
||||
print_intrcnts(unsigned long *intrcnts, unsigned long *old_intrcnts,
|
||||
char *intrnames, unsigned int nintr,
|
||||
size_t istrnamlen, long long period_ms)
|
||||
{
|
||||
unsigned long *intrcnt, *old_intrcnt;
|
||||
uint64_t inttotal, old_inttotal, total_count, total_rate;
|
||||
char* intrname;
|
||||
unsigned int i;
|
||||
|
||||
inttotal = 0;
|
||||
old_inttotal = 0;
|
||||
intrname = intrnames;
|
||||
for (i = 0, intrcnt=intrcnts, old_intrcnt=old_intrcnts; i < nintr; i++) {
|
||||
if (intrname[0] != '\0' && (*intrcnt != 0 || aflag)) {
|
||||
unsigned long count, rate;
|
||||
|
||||
count = *intrcnt - *old_intrcnt;
|
||||
rate = (count * 1000 + period_ms / 2) / period_ms;
|
||||
(void)printf("%-*s %20lu %10lu\n", (int)istrnamlen,
|
||||
intrname, count, rate);
|
||||
}
|
||||
intrname += strlen(intrname) + 1;
|
||||
inttotal += *intrcnt++;
|
||||
old_inttotal += *old_intrcnt++;
|
||||
}
|
||||
total_count = inttotal - old_inttotal;
|
||||
total_rate = (total_count * 1000 + period_ms / 2) / period_ms;
|
||||
(void)printf("%-*s %20" PRIu64 " %10" PRIu64 "\n", (int)istrnamlen,
|
||||
"Total", total_count, total_rate);
|
||||
}
|
||||
|
||||
static void
|
||||
dointr(unsigned int interval, int reps)
|
||||
{
|
||||
unsigned long *intrcnts;
|
||||
long long uptime, period_ms;
|
||||
unsigned long *old_intrcnts = NULL;
|
||||
size_t clen, inamlen, istrnamlen;
|
||||
char *intrnames, *intrname;
|
||||
|
||||
uptime = getuptime();
|
||||
|
||||
/* Get the names of each interrupt source */
|
||||
if (kd != NULL) {
|
||||
kread(X_SINTRNAMES, &inamlen, sizeof(inamlen));
|
||||
if ((intrnames = malloc(inamlen)) == NULL)
|
||||
err(1, "malloc()");
|
||||
kread(X_INTRNAMES, intrnames, inamlen);
|
||||
} else {
|
||||
for (intrnames = NULL, inamlen = 1024; ; inamlen *= 2) {
|
||||
if ((intrnames = reallocf(intrnames, inamlen)) == NULL)
|
||||
err(1, "reallocf()");
|
||||
if (mysysctl("hw.intrnames",
|
||||
intrnames, &inamlen, NULL, 0) == 0)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/* Determine the length of the longest interrupt name */
|
||||
intrname = intrnames;
|
||||
istrnamlen = strlen("interrupt");
|
||||
for (i = 0; i < nintr; i++) {
|
||||
clen = strlen(tintrname);
|
||||
while(*intrname != '\0') {
|
||||
clen = strlen(intrname);
|
||||
if (clen > istrnamlen)
|
||||
istrnamlen = clen;
|
||||
tintrname += clen + 1;
|
||||
intrname += strlen(intrname) + 1;
|
||||
}
|
||||
(void)printf("%-*s %20s %10s\n", (int)istrnamlen, "interrupt", "total",
|
||||
"rate");
|
||||
inttotal = 0;
|
||||
for (i = 0; i < nintr; i++) {
|
||||
if (intrname[0] != '\0' && (*intrcnt != 0 || aflag))
|
||||
(void)printf("%-*s %20lu %10lu\n", (int)istrnamlen,
|
||||
intrname, *intrcnt, *intrcnt / uptime);
|
||||
intrname += strlen(intrname) + 1;
|
||||
inttotal += *intrcnt++;
|
||||
|
||||
/*
|
||||
* Loop reps times printing differential interrupt counts. If reps is
|
||||
* zero, then run just once, printing total counts
|
||||
*/
|
||||
period_ms = uptime / 1000000;
|
||||
while(1) {
|
||||
unsigned int nintr;
|
||||
long long old_uptime;
|
||||
|
||||
nintr = read_intrcnts(&intrcnts);
|
||||
/*
|
||||
* Initialize old_intrcnts to 0 for the first pass, so
|
||||
* print_intrcnts will print total interrupts since boot
|
||||
*/
|
||||
if (old_intrcnts == NULL) {
|
||||
old_intrcnts = calloc(nintr, sizeof(unsigned long));
|
||||
if (old_intrcnts == NULL)
|
||||
err(1, "calloc()");
|
||||
}
|
||||
|
||||
print_intrcnts(intrcnts, old_intrcnts, intrnames, nintr,
|
||||
istrnamlen, period_ms);
|
||||
|
||||
free(old_intrcnts);
|
||||
old_intrcnts = intrcnts;
|
||||
if (reps >= 0 && --reps <= 0)
|
||||
break;
|
||||
usleep(interval * 1000);
|
||||
old_uptime = uptime;
|
||||
uptime = getuptime();
|
||||
period_ms = (uptime - old_uptime) / 1000000;
|
||||
}
|
||||
(void)printf("%-*s %20" PRIu64 " %10" PRIu64 "\n", (int)istrnamlen,
|
||||
"Total", inttotal, inttotal / uptime);
|
||||
}
|
||||
|
||||
static void
|
||||
|
@ -178,7 +178,7 @@ Config_spec:
|
||||
} |
|
||||
OPTIONS Opt_list
|
||||
|
|
||||
NOOPTION Save_id { rmopt_schedule(&opt, $2); } |
|
||||
NOOPTION NoOpt_list |
|
||||
MAKEOPTIONS Mkopt_list
|
||||
|
|
||||
NOMAKEOPTION Save_id { rmopt_schedule(&mkopt, $2); } |
|
||||
@ -225,6 +225,11 @@ Opt_list:
|
||||
Option
|
||||
;
|
||||
|
||||
NoOpt_list:
|
||||
NoOpt_list COMMA NoOption
|
||||
|
|
||||
NoOption
|
||||
;
|
||||
Option:
|
||||
Save_id {
|
||||
newopt(&opt, $1, NULL, 0);
|
||||
@ -236,6 +241,11 @@ Option:
|
||||
newopt(&opt, $1, $3, 0);
|
||||
} ;
|
||||
|
||||
NoOption:
|
||||
Save_id {
|
||||
rmopt_schedule(&opt, $1);
|
||||
};
|
||||
|
||||
Opt_value:
|
||||
ID { $$ = $1; } |
|
||||
NUMBER {
|
||||
|
@ -49,5 +49,5 @@
|
||||
*
|
||||
* $FreeBSD$
|
||||
*/
|
||||
#define CONFIGVERS 600013
|
||||
#define CONFIGVERS 600014
|
||||
#define MAJOR_VERS(x) ((x) / 100000)
|
||||
|
@ -726,15 +726,17 @@ static void
|
||||
devstats(int perf_select, long double etime, int havelast)
|
||||
{
|
||||
int dn;
|
||||
long double transfers_per_second, transfers_per_second_read, transfers_per_second_write;
|
||||
long double kb_per_transfer, mb_per_second, mb_per_second_read, mb_per_second_write;
|
||||
long double transfers_per_second, transfers_per_second_read;
|
||||
long double transfers_per_second_write;
|
||||
long double kb_per_transfer, mb_per_second, mb_per_second_read;
|
||||
long double mb_per_second_write;
|
||||
u_int64_t total_bytes, total_transfers, total_blocks;
|
||||
u_int64_t total_bytes_read, total_transfers_read;
|
||||
u_int64_t total_bytes_write, total_transfers_write;
|
||||
long double busy_pct, busy_time;
|
||||
u_int64_t queue_len;
|
||||
long double total_mb;
|
||||
long double blocks_per_second, ms_per_transaction, total_duration;
|
||||
long double total_mb, blocks_per_second, total_duration;
|
||||
long double ms_per_other, ms_per_read, ms_per_write, ms_per_transaction;
|
||||
int firstline = 1;
|
||||
char *devname;
|
||||
|
||||
@ -746,8 +748,8 @@ devstats(int perf_select, long double etime, int havelast)
|
||||
printf(" cpu ");
|
||||
printf("\n");
|
||||
if (Iflag == 0) {
|
||||
printf("device r/s w/s kr/s kw/s qlen "
|
||||
"svc_t %%b ");
|
||||
printf("device r/s w/s kr/s kw/s "
|
||||
" ms/r ms/w ms/o ms/t qlen %%b ");
|
||||
} else {
|
||||
printf("device r/i w/i kr/i"
|
||||
" kw/i qlen tsvc_t/i sb/i ");
|
||||
@ -786,6 +788,9 @@ devstats(int perf_select, long double etime, int havelast)
|
||||
DSM_MB_PER_SECOND_WRITE, &mb_per_second_write,
|
||||
DSM_BLOCKS_PER_SECOND, &blocks_per_second,
|
||||
DSM_MS_PER_TRANSACTION, &ms_per_transaction,
|
||||
DSM_MS_PER_TRANSACTION_READ, &ms_per_read,
|
||||
DSM_MS_PER_TRANSACTION_WRITE, &ms_per_write,
|
||||
DSM_MS_PER_TRANSACTION_OTHER, &ms_per_other,
|
||||
DSM_BUSY_PCT, &busy_pct,
|
||||
DSM_QUEUE_LENGTH, &queue_len,
|
||||
DSM_TOTAL_DURATION, &total_duration,
|
||||
@ -820,13 +825,18 @@ devstats(int perf_select, long double etime, int havelast)
|
||||
mb_per_second_write > ((long double).0005)/1024 ||
|
||||
busy_pct > 0.5) {
|
||||
if (Iflag == 0)
|
||||
printf("%-8.8s %5.1Lf %5.1Lf %7.1Lf %7.1Lf %4" PRIu64 " %5.1Lf %3.0Lf ",
|
||||
devname, transfers_per_second_read,
|
||||
transfers_per_second_write,
|
||||
printf("%-8.8s %5d %5d %8.1Lf "
|
||||
"%8.1Lf %5d %5d %5d %5d "
|
||||
"%4" PRIu64 " %3.0Lf ",
|
||||
devname,
|
||||
(int)transfers_per_second_read,
|
||||
(int)transfers_per_second_write,
|
||||
mb_per_second_read * 1024,
|
||||
mb_per_second_write * 1024,
|
||||
queue_len,
|
||||
ms_per_transaction, busy_pct);
|
||||
(int)ms_per_read, (int)ms_per_write,
|
||||
(int)ms_per_other,
|
||||
(int)ms_per_transaction,
|
||||
queue_len, busy_pct);
|
||||
else
|
||||
printf("%-8.8s %11.1Lf %11.1Lf "
|
||||
"%12.1Lf %12.1Lf %4" PRIu64
|
||||
|
@ -68,7 +68,11 @@ pw_group(struct userconf * cnf, int mode, struct cargs * args)
|
||||
};
|
||||
|
||||
if (a_gid != NULL) {
|
||||
if (strspn(a_gid->val, "0123456789") != strlen(a_gid->val))
|
||||
const char *teststr;
|
||||
teststr = a_gid->val;
|
||||
if (*teststr == '-')
|
||||
teststr++;
|
||||
if (strspn(teststr, "0123456789") != strlen(teststr))
|
||||
errx(EX_USAGE, "-g expects a number");
|
||||
}
|
||||
|
||||
|
@ -322,7 +322,10 @@ pw_user(struct userconf * cnf, int mode, struct cargs * args)
|
||||
a_name = NULL;
|
||||
}
|
||||
} else {
|
||||
if (strspn(a_uid->val, "0123456789") != strlen(a_uid->val))
|
||||
const char *teststr = a_uid->val;
|
||||
if (*teststr == '-')
|
||||
teststr++;
|
||||
if (strspn(teststr, "0123456789") != strlen(teststr))
|
||||
errx(EX_USAGE, "-u expects a number");
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user