Merge ^/head r314270 through r314419.

This commit is contained in:
Dimitry Andric 2017-02-28 21:30:26 +00:00
commit be64968040
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/projects/clang400-import/; revision=314421
274 changed files with 6824 additions and 16393 deletions

View File

@ -151,6 +151,11 @@ OLD_FILES+=usr/lib/clang/3.9.1/lib/freebsd/libclang_rt.ubsan_standalone_cxx-x86_
OLD_DIRS+=usr/lib/clang/3.9.1/lib/freebsd
OLD_DIRS+=usr/lib/clang/3.9.1/lib
OLD_DIRS+=usr/lib/clang/3.9.1
# 20170226: SVR4 compatibility removed
.if ${TARGET_ARCH} == "amd64" || ${TARGET_ARCH} == "i386"
OLD_FILES+=usr/share/man/man4/streams.4
OLD_FILES+=usr/share/man/man4/svr4.4
.endif
# 20170219: OpenPAM RADULA upgrade removed the libpam tests
OLD_FILES+=usr/tests/lib/libpam/Kyuafile
OLD_FILES+=usr/tests/lib/libpam/t_openpam_ctype
@ -8454,7 +8459,7 @@ OLD_FILES+=usr/share/man/man8/boot_i386.8.gz
.endif
.if ${TARGET_ARCH} != "aarch64" && ${TARGET} != "arm" && \
${TARGET_ARCH} != "powerpc" && ${TARGET_ARCH} != "powerpc64" && \
${TARGET_ARCH} != "sparc64"
${TARGET_ARCH} != "sparc64" && ${TARGET} != "mips"
OLD_FILES+=usr/share/man/man8/ofwdump.8.gz
.endif
OLD_FILES+=usr/share/man/man8/mount_reiserfs.8.gz

View File

@ -30,7 +30,7 @@ export PATH=/bin:/sbin:/usr/bin:/usr/sbin
unset LD_LIBRARY_PATH
# generate config.h with krb5 and stash it
sh configure $configure_args --with-kerberos5
sh configure $configure_args --with-kerberos5=/usr
mv config.log config.log.orig
mv config.h config.h.orig

View File

@ -319,7 +319,6 @@ add_local_forward(Options *options, const struct Forward *newfwd)
#else
ipport_reserved = IPPORT_RESERVED;
#endif
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0)
if (newfwd->listen_port < ipport_reserved && original_real_uid != 0 &&
newfwd->listen_path == NULL)
fatal("Privileged ports can only be forwarded by root.");

View File

@ -630,7 +630,6 @@ firstboot_sentinel="/firstboot" # Scripts with "firstboot" keyword are run if
# Emulation/compatibility services provided by /etc/rc.d/abi
sysvipc_enable="NO" # Load System V IPC primitives at startup (or NO).
linux_enable="NO" # Linux binary compatibility loaded at startup (or NO).
svr4_enable="NO" # SysVR4 emulation loaded at startup (or NO).
clear_tmp_enable="NO" # Clear /tmp at startup.
clear_tmp_X="YES" # Clear and recreate X11-related directories in /tmp
ldconfig_insecure="NO" # Set to YES to disable ldconfig security checks

View File

@ -312,10 +312,10 @@ notify 10 {
};
# This example works around a memory leak in PostgreSQL, restarting
# it when the "user:pgsql:swap:devctl=1G" rctl(8) rule gets triggered.
# it when the "user:postgres:swap:devctl=1G" rctl(8) rule gets triggered.
notify 0 {
match "system" "RCTL";
match "rule" "user:70:swap:.*";
match "rule" "user:770:swap:.*";
action "/usr/local/etc/rc.d/postgresql restart";
};

View File

@ -43,25 +43,18 @@ linux_start()
fi
}
svr4_start()
{
echo -n ' svr4'
load_kld -m svr4elf svr4
}
abi_start()
{
local _echostop
_echostop=
if checkyesno sysvipc_enable || checkyesno linux_enable || checkyesno svr4_enable; then
if checkyesno sysvipc_enable || checkyesno linux_enable; then
echo -n 'Additional ABI support:'
_echostop=yes
fi
checkyesno sysvipc_enable && sysv_start
checkyesno linux_enable && linux_start
checkyesno svr4_enable && svr4_start
[ -n "${_echostop}" ] && echo '.'
}

View File

@ -175,6 +175,7 @@ typedef struct {
#define T_ATMA ns_t_atma
#define T_NAPTR ns_t_naptr
#define T_A6 ns_t_a6
#define T_DNAME ns_t_dname
#define T_OPT ns_t_opt
#define T_TSIG ns_t_tsig
#define T_IXFR ns_t_ixfr

View File

@ -319,7 +319,7 @@ The additional word delimiters
and
.Ql \e>
are provided to ease compatibility with traditional
.Xr svr4 4
SVR4
systems but are not portable and should be avoided.
.Pp
In the event that an RE could match more than one substring of a given

View File

@ -33,6 +33,7 @@ __FBSDID("$FreeBSD$");
#include <sys/param.h>
#include "namespace.h"
#include <sys/capsicum.h>
#include <sys/elf.h>
#include <sys/fcntl.h>
#include <sys/mman.h>
@ -124,6 +125,7 @@ __vdso_init_hpet(uint32_t u)
static const char devprefix[] = "/dev/hpet";
char devname[64], *c, *c1, t;
volatile char *new_map, *old_map;
unsigned int mode;
uint32_t u1;
int fd;
@ -144,18 +146,25 @@ __vdso_init_hpet(uint32_t u)
if (old_map != NULL)
return;
if (cap_getmode(&mode) == 0 && mode != 0)
goto fail;
fd = _open(devname, O_RDONLY);
if (fd == -1) {
atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
(uintptr_t)old_map, (uintptr_t)MAP_FAILED);
return;
}
if (fd == -1)
goto fail;
new_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0);
_close(fd);
if (atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
(uintptr_t)old_map, (uintptr_t)new_map) == 0 &&
new_map != MAP_FAILED)
munmap((void *)new_map, PAGE_SIZE);
munmap((void *)new_map, PAGE_SIZE);
return;
fail:
/* Prevent the caller from re-entering. */
atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u],
(uintptr_t)old_map, (uintptr_t)MAP_FAILED);
}
#ifdef WANT_HYPERV
@ -174,16 +183,22 @@ static void
__vdso_init_hyperv_tsc(void)
{
int fd;
unsigned int mode;
if (cap_getmode(&mode) == 0 && mode != 0)
goto fail;
fd = _open(HYPERV_REFTSC_DEVPATH, O_RDONLY);
if (fd < 0) {
/* Prevent the caller from re-entering. */
hyperv_ref_tsc = MAP_FAILED;
return;
}
if (fd < 0)
goto fail;
hyperv_ref_tsc = mmap(NULL, sizeof(*hyperv_ref_tsc), PROT_READ,
MAP_SHARED, fd, 0);
_close(fd);
return;
fail:
/* Prevent the caller from re-entering. */
hyperv_ref_tsc = MAP_FAILED;
}
static int

View File

@ -153,7 +153,7 @@ fetch_syserr(void)
case EHOSTDOWN:
fetchLastErrCode = FETCH_DOWN;
break;
default:
default:
fetchLastErrCode = FETCH_UNKNOWN;
}
snprintf(fetchLastErrString, MAXERRSTRING, "%s", strerror(errno));
@ -371,7 +371,7 @@ fetch_connect(const char *host, int port, int af, int verbose)
}
if (err != 0) {
if (verbose)
fetch_info("failed to connect to %s:%s", host, port);
fetch_info("failed to connect to %s:%d", host, port);
goto syserr;
}

View File

@ -244,10 +244,10 @@ rss_config_get(void)
return (rc);
error:
if ((rc != NULL) && rc->rss_bucket_map)
if (rc != NULL) {
free(rc->rss_bucket_map);
if (rc != NULL)
free(rc);
}
return (NULL);
}

View File

@ -1146,6 +1146,18 @@ variables can be used to control the behavior of the
GEOM class.
The default value is shown next to each variable.
.Bl -tag -width indent
.It Va kern.geom.part.auto_resize: No 1
This variable controls automatic resize behavior of
.Nm
GEOM class.
When this variable is enable and new size of provider is detected, the schema
metadata is resized but all changes are not saved to disk, until
.Cm gpart commit
is run to confirm changes.
This behavior is also reported with diagnostic message:
.Sy "GEOM_PART: (provider) was automatically resized."
.Sy "Use `gpart commit (provider)` to save changes or `gpart undo (provider)`"
.Sy "to revert them."
.It Va kern.geom.part.check_integrity : No 1
This variable controls the behaviour of metadata integrity checks.
When integrity checks are enabled, the

View File

@ -29,7 +29,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd February 6, 2017
.Dd February 27, 2017
.Dt SETKEY 8
.Os
.\"
@ -593,12 +593,11 @@ keyed-md5 128 ah: 96bit ICV (no document)
keyed-sha1 160 ah: 96bit ICV (no document)
160 ah-old: 128bit ICV (no document)
null 0 to 2048 for debugging
hmac-sha2-256 256 ah: 96bit ICV
(draft-ietf-ipsec-ciph-sha-256-00)
hmac-sha2-256 256 ah: 128bit ICV (RFC4868)
256 ah-old: 128bit ICV (no document)
hmac-sha2-384 384 ah: 96bit ICV (no document)
hmac-sha2-384 384 ah: 192bit ICV (RFC4868)
384 ah-old: 128bit ICV (no document)
hmac-sha2-512 512 ah: 96bit ICV (no document)
hmac-sha2-512 512 ah: 256bit ICV (RFC4868)
512 ah-old: 128bit ICV (no document)
hmac-ripemd160 160 ah: 96bit ICV (RFC2857)
ah-old: 128bit ICV (no document)

View File

@ -25,8 +25,6 @@ MAN= aic.4 \
pnpbios.4 \
sbni.4 \
smapi.4 \
streams.4 \
svr4.4 \
vpd.4 \
vx.4

View File

@ -1,85 +0,0 @@
.\" Copyright (c) 2000 Mark Newton
.\" 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$
.\"
.Dd March 17, 2008
.Dt STREAMS 4 i386
.Os
.Sh NAME
.Nm streams
.Nd System V STREAMS networking ABI support
.Sh SYNOPSIS
To compile support for this ABI into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "device streams"
.Ed
.Pp
Alternatively, to load the ABI as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
streams_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
module provides limited
System V Release 4 STREAMS interprocess communication ABI
(application binary interface) compatibility
for userland applications.
.Pp
Internally,
.Nm
provides STREAMS handles by using socket creation kernel routines, and
adding state-tracking information to the socket to permit manipulation
by STREAMS emulation code in
.Xr svr4 4 .
Hence, opening a stream device produces a result similar to what would be
obtained by calling
.Xr socket 2 .
.Pp
Applications should never use this interface directly: STREAMS
emulation is only provided as a service to support ABI requirements in
the SVR4 environment which
.Xr svr4 4
needs to present to client binaries.
.Sh SEE ALSO
.Xr svr4 4
.Sh HISTORY
System V Release 4 ABI support first appeared in
.Fx 4.0 .
The ABI was ported from an equivalent facility present in
.Nx 1.3
written by Christos Zoulas.
.Sh BUGS
This whole interface is a crude hack to produce STREAMS semantics
through emulation over sockets.
.Pp
Programmers who hope to be able to use this interface to provide
SVR4 STREAMS services to
.Bx
applications will be sorely disappointed.

View File

@ -1,225 +0,0 @@
.\" Copyright (c) 2000 Mark Newton
.\" 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$
.\"
.Dd March 17, 2008
.Dt SVR4 4 i386
.Os
.Sh NAME
.Nm svr4
.Nd System V Release 4 ABI support
.Sh SYNOPSIS
To compile support for this ABI into the kernel,
place the following line in your
kernel configuration file:
.Bd -ragged -offset indent
.Cd "options COMPAT_SVR4"
.Ed
.Pp
Alternatively, to load the ABI as a
module at boot time, place the following line in
.Xr loader.conf 5 :
.Bd -literal -offset indent
svr4_load="YES"
.Ed
.Sh DESCRIPTION
The
.Nm
module provides limited
System V Release 4 ABI (application binary interface) compatibility
for userland applications.
The module provides the following significant facilities:
.Bl -bullet
.It
An image activator
for correctly branded
.Xr elf 5
executable images
.It
Special signal handling for activated images
.It
SVR4 to native system call translation
.It
STREAMS network API emulation (via the
.Xr streams 4
loadable module, or by means of
.Dl device streams
in a kernel configuration file)
.It
Mappings between
.Fx
and SVR4
.Xr ioctl 2
calls, or, where no such mappings exist, reverse-engineered implementations
of the SVR4 calls.
.El
.Pp
It is important to note that the SVR4 ABI support
it not provided through an emulator.
Rather, a true (albeit limited) "clean room" reverse-engineered ABI
implementation is provided.
.Sh LIMITATIONS
Because the provided ABI has been developed in ignorance of actual SVR4
source code, there are bound to be unforeseen interactions between SVR4
client applications and the emulated ABI which cause applications to
malfunction.
.Pp
Additionally, some SVR4 operating systems do not adhere to the SVR4
ELF standard.
In particular, Solaris does not set the ELF interpreter field in the
ELF header to a value which would allow the kernel to correctly
identify a client executable as an SVR4 application.
Thus, in certain instances it is necessary to use the
.Xr brandelf 1
utility to explicitly brand the executable, or to set the
kern.fallback_elf_brand
.Xr sysctl 8
variable to define a "default" ABI for unbranded executables.
Value ELFOSABI_SOLARIS represents Solaris; ELFOSABI_SYSV represents other
SysVR4 operating systems.
See
.In sys/elf_common.h
for ELFOSABI branding definitions, and
.Xr brandelf 1
for information on branding executables.
.Pp
The
.Nm
module can be linked into the kernel statically with the
.Dv COMPAT_SVR4
kernel configuration option
or loaded as required.
The following command will load the module
if it is neither linked into the kernel
nor already loaded as a module:
.Bd -literal -offset indent
if ! kldstat -v | grep -E 'svr4elf' > /dev/null; then
kldload svr4 > /dev/null 2>&1
fi
.Ed
.Pp
The kernel
will check for the presence of the
.Xr streams 4
module, and load it if necessary.
.Pp
Note that dynamically linked SVR4 executables
will require a suitable environment in
.Pa /compat/svr4 .
.Pp
For information on loading the
.Nm
kernel loadable module automatically on system startup,
see
.Xr rc.conf 5 .
This information applies
regardless of whether the
.Nm
module is statically linked into the kernel
or loaded as a module.
.Pp
STREAMS emulation is limited but (largely) functional.
Assuming the
.Xr streams 4
module is loaded, a STREAMS handle can be obtained by opening one of the
relevant files in
.Pa /dev
or
.Pa /compat/svr4/dev .
Internally, the
.Xr streams 4
driver produces a socket descriptor and
.Dq tags
it with additional STREAMS
state information before returning it to the client application.
The
.Nm
environment uses the additional state information to recognize and
manipulate emulated STREAMS handles when STREAMS-specific
.Xr ioctl 2
calls are executed.
.Pp
The subset of STREAMS functionality which is provided is small, probably
little more than what is required to enable programs on the Solaris CD
sets to run.
.Sh FILES
.Bl -tag -width /sys/compat/svr4/syscalls.master -compact
.It Pa /compat/svr4
minimal SVR4 run-time environment
.It Pa /sys/compat/svr4/syscalls.master
mappings between SVR4 syscalls and
.Nm
module entrypoints.
.El
.Sh SEE ALSO
.Xr brandelf 1 ,
.Xr streams 4 ,
.Xr elf 5
.Sh HISTORY
System V Release 4 ABI support first appeared in
.Fx 4.0 .
The ABI was ported from an equivalent facility present in
.Nx 1.3
written by Christos Zoulas.
.Sh BUGS
Emulation of signal handlers is buggy.
.Pp
Emulated connectionless STREAMS fail to receive data from the network in
some circumstances (but succeed in others -- probably due to particular
ways of initializing them which the
.Xr streams 4
module is mishandling, and interaction between STREAMS and
.Xr poll 2 ) .
Connection-oriented STREAMS appear to be functional.
.Pp
Ironically, this SVR4 emulator does not (yet) support SVR4 semaphores or
shared memory.
.Pp
.Xr ports 7
to automatically create the
.Pa /compat/svr4
environment do not exist.
.Xr tar 1
archives containing pre-populated trees can be obtained from
.Pa http://people.FreeBSD.org/~newton/freebsd-svr4/ .
.Pp
Extensive testing has only really been carried out with Solaris 2.x binaries,
with anecdotal reports of limited success coming from testers with
early-revision SCO media.
In theory, the basic SVR4 ABI should be constant
across the set of vendors who produce SVR4 operating systems, but in
practice that is probably not the case.
If necessary, future work can
either implement additional
.Xr kld 4
modules which produce functionality which contains OS-dependent
departures from the behaviour which has been implemented in this
ABI implementation.
Alternatively,
.Xr sysctl 8
variables could set the
.Dq personality
the environment should present to
client applications.

View File

@ -24,7 +24,7 @@
.\"
.\" $FreeBSD$
.\"
.Dd December 10, 2016
.Dd February 26, 2017
.Dt RC.CONF 5
.Os
.Sh NAME
@ -3631,11 +3631,6 @@ Set to
.Dq Li YES
to enable Linux/ELF binary emulation at system initial
boot time.
.It Va svr4_enable
.Pq Vt bool
If set to
.Dq Li YES ,
enable SysVR4 emulation at boot time.
.It Va sysvipc_enable
.Pq Vt bool
If set to

View File

@ -57,7 +57,8 @@
.Nm sbuf_delete ,
.Nm sbuf_start_section ,
.Nm sbuf_end_section ,
.Nm sbuf_hexdump
.Nm sbuf_hexdump ,
.Nm sbuf_putbuf
.Nd safe string composition
.Sh SYNOPSIS
.In sys/types.h
@ -124,6 +125,8 @@
.Fa "const char *hdr"
.Fa "int flags"
.Fc
.Ft void
.Fn sbuf_putbuf "struct sbuf *s"
.In sys/sysctl.h
.Ft struct sbuf *
.Fn sbuf_new_for_sysctl "struct sbuf *s" "char *buf" "int length" "struct sysctl_req *req"
@ -472,6 +475,12 @@ representation of the bytes if possible.
See the
.Xr hexdump 3
man page for more details on the interface.
.Pp
The
.Fn sbuf_putbuf
function printfs the sbuf to stdout if in userland, and to the console
and log if in the kernel.
It does not drain the buffer or update any pointers.
.Sh NOTES
If an operation caused an
.Fa sbuf

View File

@ -613,6 +613,8 @@ static vm_page_t pmap_enter_quick_locked(pmap_t pmap, vm_offset_t va,
vm_page_t m, vm_prot_t prot, vm_page_t mpte, struct rwlock **lockp);
static void pmap_fill_ptp(pt_entry_t *firstpte, pt_entry_t newpte);
static int pmap_insert_pt_page(pmap_t pmap, vm_page_t mpte);
static void pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va,
pd_entry_t pde);
static void pmap_kenter_attr(vm_offset_t va, vm_paddr_t pa, int mode);
static void pmap_pde_attr(pd_entry_t *pde, int cache_bits, int mask);
static void pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
@ -1838,6 +1840,27 @@ pmap_update_pde(pmap_t pmap, vm_offset_t va, pd_entry_t *pde, pd_entry_t newpde)
}
#endif /* !SMP */
static void
pmap_invalidate_pde_page(pmap_t pmap, vm_offset_t va, pd_entry_t pde)
{
/*
* When the PDE has PG_PROMOTED set, the 2MB page mapping was created
* by a promotion that did not invalidate the 512 4KB page mappings
* that might exist in the TLB. Consequently, at this point, the TLB
* may hold both 4KB and 2MB page mappings for the address range [va,
* va + NBPDR). Therefore, the entire range must be invalidated here.
* In contrast, when PG_PROMOTED is clear, the TLB will not hold any
* 4KB page mappings for the address range [va, va + NBPDR), and so a
* single INVLPG suffices to invalidate the 2MB page mapping from the
* TLB.
*/
if ((pde & PG_PROMOTED) != 0)
pmap_invalidate_range(pmap, va, va + NBPDR - 1);
else
pmap_invalidate_page(pmap, va);
}
#define PMAP_CLFLUSH_THRESHOLD (2 * 1024 * 1024)
void
@ -3472,7 +3495,8 @@ pmap_demote_pde_locked(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
SLIST_INIT(&free);
sva = trunc_2mpage(va);
pmap_remove_pde(pmap, pde, sva, &free, lockp);
pmap_invalidate_range(pmap, sva, sva + NBPDR - 1);
if ((oldpde & PG_G) == 0)
pmap_invalidate_pde_page(pmap, sva, oldpde);
pmap_free_zero_pages(&free);
CTR2(KTR_PMAP, "pmap_demote_pde: failure for va %#lx"
" in pmap %p", va, pmap);
@ -3612,25 +3636,8 @@ pmap_remove_pde(pmap_t pmap, pd_entry_t *pdq, vm_offset_t sva,
oldpde = pte_load_clear(pdq);
if (oldpde & PG_W)
pmap->pm_stats.wired_count -= NBPDR / PAGE_SIZE;
/*
* When workaround_erratum383 is false, a promotion to a 2M
* page mapping does not invalidate the 512 4K page mappings
* from the TLB. Consequently, at this point, the TLB may
* hold both 4K and 2M page mappings. Therefore, the entire
* range of addresses must be invalidated here. In contrast,
* when workaround_erratum383 is true, a promotion does
* invalidate the 512 4K page mappings, and so a single INVLPG
* suffices to invalidate the 2M page mapping.
*/
if ((oldpde & PG_G) != 0) {
if (workaround_erratum383)
pmap_invalidate_page(kernel_pmap, sva);
else
pmap_invalidate_range(kernel_pmap, sva,
sva + NBPDR - 1);
}
if ((oldpde & PG_G) != 0)
pmap_invalidate_pde_page(kernel_pmap, sva, oldpde);
pmap_resident_count_dec(pmap, NBPDR / PAGE_SIZE);
if (oldpde & PG_MANAGED) {
CHANGE_PV_LIST_LOCK_TO_PHYS(lockp, oldpde & PG_PS_FRAME);
@ -4010,16 +4017,16 @@ pmap_protect_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t sva, vm_prot_t prot)
if ((prot & VM_PROT_EXECUTE) == 0)
newpde |= pg_nx;
if (newpde != oldpde) {
if (!atomic_cmpset_long(pde, oldpde, newpde))
/*
* As an optimization to future operations on this PDE, clear
* PG_PROMOTED. The impending invalidation will remove any
* lingering 4KB page mappings from the TLB.
*/
if (!atomic_cmpset_long(pde, oldpde, newpde & ~PG_PROMOTED))
goto retry;
if (oldpde & PG_G) {
/* See pmap_remove_pde() for explanation. */
if (workaround_erratum383)
pmap_invalidate_page(kernel_pmap, sva);
else
pmap_invalidate_range(kernel_pmap, sva,
sva + NBPDR - 1);
} else
if ((oldpde & PG_G) != 0)
pmap_invalidate_pde_page(kernel_pmap, sva, oldpde);
else
anychanged = TRUE;
}
return (anychanged);
@ -4272,7 +4279,7 @@ pmap_promote_pde(pmap_t pmap, pd_entry_t *pde, vm_offset_t va,
if (workaround_erratum383)
pmap_update_pde(pmap, va, pde, PG_PS | newpde);
else
pde_store(pde, PG_PS | newpde);
pde_store(pde, PG_PROMOTED | PG_PS | newpde);
atomic_add_long(&pmap_pde_promotions, 1);
CTR2(KTR_PMAP, "pmap_promote_pde: success for va %#lx"
@ -4585,7 +4592,8 @@ pmap_enter_pde(pmap_t pmap, vm_offset_t va, vm_page_t m, vm_prot_t prot,
pmap_resident_count_inc(pmap, NBPDR / PAGE_SIZE);
/*
* Map the superpage.
* Map the superpage. (This is not a promoted mapping; there will not
* be any lingering 4KB page mappings in the TLB.)
*/
pde_store(pde, newpde);

View File

@ -633,27 +633,6 @@ options LINPROCFS
# and PSEUDOFS)
options LINSYSFS
#
# SysVR4 ABI emulation
#
# The svr4 ABI emulator can be statically compiled into the kernel or loaded as
# a KLD module.
# The STREAMS network emulation code can also be compiled statically or as a
# module. If loaded as a module, it must be loaded before the svr4 module
# (the /usr/sbin/svr4 script does this for you). If compiling statically,
# the `streams' device must be configured into any kernel which also
# specifies COMPAT_SVR4. It is possible to have a statically-configured
# STREAMS device and a dynamically loadable svr4 emulator; the /usr/sbin/svr4
# script understands that it doesn't need to load the `streams' module under
# those circumstances.
# Caveat: At this time, `options KTRACE' is required for the svr4 emulator
# (whether static or dynamic).
#
#XXX#options COMPAT_SVR4 # build emulator statically
#XXX#options DEBUG_SVR4 # enable verbose debugging
#XXX#device streams # STREAMS network driver (required for svr4).
#####################################################################
# VM OPTIONS

View File

@ -109,6 +109,7 @@
#define PG_MANAGED X86_PG_AVAIL2
#define EPT_PG_EMUL_V X86_PG_AVAIL(52)
#define EPT_PG_EMUL_RW X86_PG_AVAIL(53)
#define PG_PROMOTED X86_PG_AVAIL(54) /* PDE only */
#define PG_FRAME (0x000ffffffffff000ul)
#define PG_PS_FRAME (0x000fffffffe00000ul)

View File

@ -103,10 +103,6 @@ DUMMY(vmsplice);
DUMMY(move_pages);
/* linux 2.6.22: */
DUMMY(signalfd);
DUMMY(timerfd_create);
/* linux 2.6.25: */
DUMMY(timerfd_settime);
DUMMY(timerfd_gettime);
/* linux 2.6.27: */
DUMMY(signalfd4);
DUMMY(inotify_init1);

View File

@ -995,12 +995,14 @@ struct linux_epoll_pwait_args {
char maxevents_l_[PADL_(l_int)]; l_int maxevents; char maxevents_r_[PADR_(l_int)];
char timeout_l_[PADL_(l_int)]; l_int timeout; char timeout_r_[PADR_(l_int)];
char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)];
char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
};
struct linux_signalfd_args {
register_t dummy;
};
struct linux_timerfd_create_args {
register_t dummy;
char clockid_l_[PADL_(l_int)]; l_int clockid; char clockid_r_[PADR_(l_int)];
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
};
struct linux_eventfd_args {
char initval_l_[PADL_(l_uint)]; l_uint initval; char initval_r_[PADR_(l_uint)];
@ -1012,10 +1014,14 @@ struct linux_fallocate_args {
char len_l_[PADL_(l_loff_t)]; l_loff_t len; char len_r_[PADR_(l_loff_t)];
};
struct linux_timerfd_settime_args {
register_t dummy;
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
char new_value_l_[PADL_(const struct l_itimerspec *)]; const struct l_itimerspec * new_value; char new_value_r_[PADR_(const struct l_itimerspec *)];
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
};
struct linux_timerfd_gettime_args {
register_t dummy;
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
};
struct linux_accept4_args {
char s_l_[PADL_(l_int)]; l_int s; char s_r_[PADR_(l_int)];

View File

@ -300,11 +300,11 @@ struct sysent linux_sysent[] = {
{ AS(linux_utimensat_args), (sy_call_t *)linux_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 280 = linux_utimensat */
{ AS(linux_epoll_pwait_args), (sy_call_t *)linux_epoll_pwait, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 281 = linux_epoll_pwait */
{ 0, (sy_call_t *)linux_signalfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 282 = linux_signalfd */
{ 0, (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 283 = linux_timerfd_create */
{ AS(linux_timerfd_create_args), (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 283 = linux_timerfd_create */
{ AS(linux_eventfd_args), (sy_call_t *)linux_eventfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 284 = linux_eventfd */
{ AS(linux_fallocate_args), (sy_call_t *)linux_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 285 = linux_fallocate */
{ 0, (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 286 = linux_timerfd_settime */
{ 0, (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 287 = linux_timerfd_gettime */
{ AS(linux_timerfd_settime_args), (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 286 = linux_timerfd_settime */
{ AS(linux_timerfd_gettime_args), (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 287 = linux_timerfd_gettime */
{ AS(linux_accept4_args), (sy_call_t *)linux_accept4, AUE_ACCEPT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 288 = linux_accept4 */
{ 0, (sy_call_t *)linux_signalfd4, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 289 = linux_signalfd4 */
{ AS(linux_eventfd2_args), (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 290 = linux_eventfd2 */

View File

@ -2068,7 +2068,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[2] = p->maxevents; /* l_int */
iarg[3] = p->timeout; /* l_int */
uarg[4] = (intptr_t) p->mask; /* l_sigset_t * */
*n_args = 5;
iarg[5] = p->sigsetsize; /* l_size_t */
*n_args = 6;
break;
}
/* linux_signalfd */
@ -2078,7 +2079,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_timerfd_create */
case 283: {
*n_args = 0;
struct linux_timerfd_create_args *p = params;
iarg[0] = p->clockid; /* l_int */
iarg[1] = p->flags; /* l_int */
*n_args = 2;
break;
}
/* linux_eventfd */
@ -2100,12 +2104,20 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_timerfd_settime */
case 286: {
*n_args = 0;
struct linux_timerfd_settime_args *p = params;
iarg[0] = p->fd; /* l_int */
iarg[1] = p->flags; /* l_int */
uarg[2] = (intptr_t) p->new_value; /* const struct l_itimerspec * */
uarg[3] = (intptr_t) p->old_value; /* struct l_itimerspec * */
*n_args = 4;
break;
}
/* linux_timerfd_gettime */
case 287: {
*n_args = 0;
struct linux_timerfd_gettime_args *p = params;
iarg[0] = p->fd; /* l_int */
uarg[1] = (intptr_t) p->old_value; /* struct l_itimerspec * */
*n_args = 2;
break;
}
/* linux_accept4 */
@ -5635,6 +5647,9 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 4:
p = "userland l_sigset_t *";
break;
case 5:
p = "l_size_t";
break;
default:
break;
};
@ -5644,6 +5659,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_create */
case 283:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "l_int";
break;
default:
break;
};
break;
/* linux_eventfd */
case 284:
@ -5676,9 +5701,35 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_settime */
case 286:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "l_int";
break;
case 2:
p = "userland const struct l_itimerspec *";
break;
case 3:
p = "userland struct l_itimerspec *";
break;
default:
break;
};
break;
/* linux_timerfd_gettime */
case 287:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "userland struct l_itimerspec *";
break;
default:
break;
};
break;
/* linux_accept4 */
case 288:
@ -7494,6 +7545,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 282:
/* linux_timerfd_create */
case 283:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_eventfd */
case 284:
if (ndx == 0 || ndx == 1)
@ -7506,8 +7560,14 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_settime */
case 286:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_timerfd_gettime */
case 287:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_accept4 */
case 288:
if (ndx == 0 || ndx == 1)

View File

@ -473,14 +473,18 @@
280 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
const struct l_timespec *times, l_int flags); }
281 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
l_int maxevents, l_int timeout, l_sigset_t *mask); }
l_int maxevents, l_int timeout, l_sigset_t *mask, \
l_size_t sigsetsize); }
282 AUE_NULL STD { int linux_signalfd(void); }
283 AUE_NULL STD { int linux_timerfd_create(void); }
283 AUE_NULL STD { int linux_timerfd_create(l_int clockid, l_int flags); }
284 AUE_NULL STD { int linux_eventfd(l_uint initval); }
285 AUE_NULL STD { int linux_fallocate(l_int fd, l_int mode, \
l_loff_t offset, l_loff_t len); }
286 AUE_NULL STD { int linux_timerfd_settime(void); }
287 AUE_NULL STD { int linux_timerfd_gettime(void); }
286 AUE_NULL STD { int linux_timerfd_settime(l_int fd, l_int flags, \
const struct l_itimerspec *new_value, \
struct l_itimerspec *old_value); }
287 AUE_NULL STD { int linux_timerfd_gettime(l_int fd, \
struct l_itimerspec *old_value); }
288 AUE_ACCEPT STD { int linux_accept4(l_int s, l_uintptr_t addr, \
l_uintptr_t namelen, int flags); }
; linux 2.6.27:

View File

@ -250,7 +250,9 @@ struct l_statfs64 {
uint64_t f_ffree;
l_fsid_t f_fsid;
l_int f_namelen;
l_int f_spare[6];
l_int f_frsize;
l_int f_flags;
l_int f_spare[4];
} __packed;
/* sigaction flags */

View File

@ -103,10 +103,6 @@ DUMMY(move_pages);
DUMMY(getcpu);
/* linux 2.6.22: */
DUMMY(signalfd);
DUMMY(timerfd_create);
/* linux 2.6.25: */
DUMMY(timerfd_settime);
DUMMY(timerfd_gettime);
/* linux 2.6.27: */
DUMMY(signalfd4);
DUMMY(inotify_init1);

View File

@ -1051,6 +1051,7 @@ struct linux_epoll_pwait_args {
char maxevents_l_[PADL_(l_int)]; l_int maxevents; char maxevents_r_[PADR_(l_int)];
char timeout_l_[PADL_(l_int)]; l_int timeout; char timeout_r_[PADR_(l_int)];
char mask_l_[PADL_(l_sigset_t *)]; l_sigset_t * mask; char mask_r_[PADR_(l_sigset_t *)];
char sigsetsize_l_[PADL_(l_size_t)]; l_size_t sigsetsize; char sigsetsize_r_[PADR_(l_size_t)];
};
struct linux_utimensat_args {
char dfd_l_[PADL_(l_int)]; l_int dfd; char dfd_r_[PADR_(l_int)];
@ -1062,7 +1063,8 @@ struct linux_signalfd_args {
register_t dummy;
};
struct linux_timerfd_create_args {
register_t dummy;
char clockid_l_[PADL_(l_int)]; l_int clockid; char clockid_r_[PADR_(l_int)];
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
};
struct linux_eventfd_args {
char initval_l_[PADL_(l_uint)]; l_uint initval; char initval_r_[PADR_(l_uint)];
@ -1074,10 +1076,14 @@ struct linux_fallocate_args {
char len_l_[PADL_(l_loff_t)]; l_loff_t len; char len_r_[PADR_(l_loff_t)];
};
struct linux_timerfd_settime_args {
register_t dummy;
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
char flags_l_[PADL_(l_int)]; l_int flags; char flags_r_[PADR_(l_int)];
char new_value_l_[PADL_(const struct l_itimerspec *)]; const struct l_itimerspec * new_value; char new_value_r_[PADR_(const struct l_itimerspec *)];
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
};
struct linux_timerfd_gettime_args {
register_t dummy;
char fd_l_[PADL_(l_int)]; l_int fd; char fd_r_[PADR_(l_int)];
char old_value_l_[PADL_(struct l_itimerspec *)]; struct l_itimerspec * old_value; char old_value_r_[PADR_(struct l_itimerspec *)];
};
struct linux_signalfd4_args {
register_t dummy;

View File

@ -340,11 +340,11 @@ struct sysent linux32_sysent[] = {
{ AS(linux_epoll_pwait_args), (sy_call_t *)linux_epoll_pwait, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 319 = linux_epoll_pwait */
{ AS(linux_utimensat_args), (sy_call_t *)linux_utimensat, AUE_FUTIMESAT, NULL, 0, 0, 0, SY_THR_STATIC }, /* 320 = linux_utimensat */
{ 0, (sy_call_t *)linux_signalfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 321 = linux_signalfd */
{ 0, (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 322 = linux_timerfd_create */
{ AS(linux_timerfd_create_args), (sy_call_t *)linux_timerfd_create, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 322 = linux_timerfd_create */
{ AS(linux_eventfd_args), (sy_call_t *)linux_eventfd, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 323 = linux_eventfd */
{ AS(linux_fallocate_args), (sy_call_t *)linux_fallocate, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 324 = linux_fallocate */
{ 0, (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 325 = linux_timerfd_settime */
{ 0, (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 326 = linux_timerfd_gettime */
{ AS(linux_timerfd_settime_args), (sy_call_t *)linux_timerfd_settime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 325 = linux_timerfd_settime */
{ AS(linux_timerfd_gettime_args), (sy_call_t *)linux_timerfd_gettime, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 326 = linux_timerfd_gettime */
{ 0, (sy_call_t *)linux_signalfd4, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 327 = linux_signalfd4 */
{ AS(linux_eventfd2_args), (sy_call_t *)linux_eventfd2, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 328 = linux_eventfd2 */
{ AS(linux_epoll_create1_args), (sy_call_t *)linux_epoll_create1, AUE_NULL, NULL, 0, 0, 0, SY_THR_STATIC }, /* 329 = linux_epoll_create1 */

View File

@ -2169,7 +2169,8 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
iarg[2] = p->maxevents; /* l_int */
iarg[3] = p->timeout; /* l_int */
uarg[4] = (intptr_t) p->mask; /* l_sigset_t * */
*n_args = 5;
iarg[5] = p->sigsetsize; /* l_size_t */
*n_args = 6;
break;
}
/* linux_utimensat */
@ -2189,7 +2190,10 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_timerfd_create */
case 322: {
*n_args = 0;
struct linux_timerfd_create_args *p = params;
iarg[0] = p->clockid; /* l_int */
iarg[1] = p->flags; /* l_int */
*n_args = 2;
break;
}
/* linux_eventfd */
@ -2211,12 +2215,20 @@ systrace_args(int sysnum, void *params, uint64_t *uarg, int *n_args)
}
/* linux_timerfd_settime */
case 325: {
*n_args = 0;
struct linux_timerfd_settime_args *p = params;
iarg[0] = p->fd; /* l_int */
iarg[1] = p->flags; /* l_int */
uarg[2] = (intptr_t) p->new_value; /* const struct l_itimerspec * */
uarg[3] = (intptr_t) p->old_value; /* struct l_itimerspec * */
*n_args = 4;
break;
}
/* linux_timerfd_gettime */
case 326: {
*n_args = 0;
struct linux_timerfd_gettime_args *p = params;
iarg[0] = p->fd; /* l_int */
uarg[1] = (intptr_t) p->old_value; /* struct l_itimerspec * */
*n_args = 2;
break;
}
/* linux_signalfd4 */
@ -5970,6 +5982,9 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 4:
p = "userland l_sigset_t *";
break;
case 5:
p = "l_size_t";
break;
default:
break;
};
@ -5998,6 +6013,16 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_create */
case 322:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "l_int";
break;
default:
break;
};
break;
/* linux_eventfd */
case 323:
@ -6030,9 +6055,35 @@ systrace_entry_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_settime */
case 325:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "l_int";
break;
case 2:
p = "userland const struct l_itimerspec *";
break;
case 3:
p = "userland struct l_itimerspec *";
break;
default:
break;
};
break;
/* linux_timerfd_gettime */
case 326:
switch(ndx) {
case 0:
p = "l_int";
break;
case 1:
p = "userland struct l_itimerspec *";
break;
default:
break;
};
break;
/* linux_signalfd4 */
case 327:
@ -8128,6 +8179,9 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
case 321:
/* linux_timerfd_create */
case 322:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_eventfd */
case 323:
if (ndx == 0 || ndx == 1)
@ -8140,8 +8194,14 @@ systrace_return_setargdesc(int sysnum, int ndx, char *desc, size_t descsz)
break;
/* linux_timerfd_settime */
case 325:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_timerfd_gettime */
case 326:
if (ndx == 0 || ndx == 1)
p = "int";
break;
/* linux_signalfd4 */
case 327:
/* linux_eventfd2 */

View File

@ -533,19 +533,23 @@
; linux 2.6.19:
318 AUE_NULL STD { int linux_getcpu(void); }
319 AUE_NULL STD { int linux_epoll_pwait(l_int epfd, struct epoll_event *events, \
l_int maxevents, l_int timeout, l_sigset_t *mask); }
l_int maxevents, l_int timeout, l_sigset_t *mask, \
l_size_t sigsetsize); }
; linux 2.6.22:
320 AUE_FUTIMESAT STD { int linux_utimensat(l_int dfd, const char *pathname, \
const struct l_timespec *times, l_int flags); }
321 AUE_NULL STD { int linux_signalfd(void); }
322 AUE_NULL STD { int linux_timerfd_create(void); }
322 AUE_NULL STD { int linux_timerfd_create(l_int clockid, l_int flags); }
323 AUE_NULL STD { int linux_eventfd(l_uint initval); }
; linux 2.6.23:
324 AUE_NULL STD { int linux_fallocate(l_int fd, l_int mode, \
l_loff_t offset, l_loff_t len); }
; linux 2.6.25:
325 AUE_NULL STD { int linux_timerfd_settime(void); }
326 AUE_NULL STD { int linux_timerfd_gettime(void); }
325 AUE_NULL STD { int linux_timerfd_settime(l_int fd, l_int flags, \
const struct l_itimerspec *new_value, \
struct l_itimerspec *old_value); }
326 AUE_NULL STD { int linux_timerfd_gettime(l_int fd, \
struct l_itimerspec *old_value); }
; linux 2.6.27:
327 AUE_NULL STD { int linux_signalfd4(void); }
328 AUE_NULL STD { int linux_eventfd2(l_uint initval, l_int flags); }

View File

@ -1,5 +1,6 @@
# $FreeBSD$
arm/allwinner/clkng/ccu_a31.c standard
arm/allwinner/a31/a31_padconf.c standard
arm/allwinner/a31/a31_r_padconf.c standard
arm/allwinner/a31/a31s_padconf.c standard

View File

@ -0,0 +1,364 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 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$
*/
/*
* Allwinner Clock Control Unit
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <sys/rman.h>
#include <sys/kernel.h>
#include <sys/module.h>
#include <machine/bus.h>
#include <dev/fdt/simplebus.h>
#include <dev/ofw/ofw_bus.h>
#include <dev/ofw/ofw_bus_subr.h>
#include <dev/extres/clk/clk.h>
#include <dev/extres/clk/clk_gate.h>
#include <dev/extres/hwreset/hwreset.h>
#include <arm/allwinner/clkng/aw_ccung.h>
#include <arm/allwinner/clkng/aw_clk.h>
#if defined(SOC_ALLWINNER_A31)
#include <arm/allwinner/clkng/ccu_a31.h>
#endif
#if defined(SOC_ALLWINNER_H3)
#include <arm/allwinner/clkng/ccu_h3.h>
#endif
#include "clkdev_if.h"
#include "hwreset_if.h"
static struct resource_spec aw_ccung_spec[] = {
{ SYS_RES_MEMORY, 0, RF_ACTIVE },
{ -1, 0 }
};
#if defined(SOC_ALLWINNER_H3)
#define H3_CCU 1
#endif
#if defined(SOC_ALLWINNER_A31)
#define A31_CCU 2
#endif
static struct ofw_compat_data compat_data[] = {
#if defined(SOC_ALLWINNER_H3)
{ "allwinner,sun8i-h3-ccu", H3_CCU },
#endif
#if defined(SOC_ALLWINNER_A31)
{ "allwinner,sun6i-a31-ccu", A31_CCU },
#endif
{NULL, 0 }
};
#define CCU_READ4(sc, reg) bus_read_4((sc)->res, (reg))
#define CCU_WRITE4(sc, reg, val) bus_write_4((sc)->res, (reg), (val))
static int
aw_ccung_write_4(device_t dev, bus_addr_t addr, uint32_t val)
{
struct aw_ccung_softc *sc;
sc = device_get_softc(dev);
CCU_WRITE4(sc, addr, val);
return (0);
}
static int
aw_ccung_read_4(device_t dev, bus_addr_t addr, uint32_t *val)
{
struct aw_ccung_softc *sc;
sc = device_get_softc(dev);
*val = CCU_READ4(sc, addr);
return (0);
}
static int
aw_ccung_modify_4(device_t dev, bus_addr_t addr, uint32_t clr, uint32_t set)
{
struct aw_ccung_softc *sc;
uint32_t reg;
sc = device_get_softc(dev);
reg = CCU_READ4(sc, addr);
reg &= ~clr;
reg |= set;
CCU_WRITE4(sc, addr, reg);
return (0);
}
static int
aw_ccung_reset_assert(device_t dev, intptr_t id, bool reset)
{
struct aw_ccung_softc *sc;
uint32_t val;
sc = device_get_softc(dev);
if (id >= sc->nresets || sc->resets[id].offset == 0)
return (0);
mtx_lock(&sc->mtx);
val = CCU_READ4(sc, sc->resets[id].offset);
if (reset)
val &= ~(1 << sc->resets[id].shift);
else
val |= 1 << sc->resets[id].shift;
CCU_WRITE4(sc, sc->resets[id].offset, val);
mtx_unlock(&sc->mtx);
return (0);
}
static int
aw_ccung_reset_is_asserted(device_t dev, intptr_t id, bool *reset)
{
struct aw_ccung_softc *sc;
uint32_t val;
sc = device_get_softc(dev);
if (id >= sc->nresets || sc->resets[id].offset == 0)
return (0);
mtx_lock(&sc->mtx);
val = CCU_READ4(sc, sc->resets[id].offset);
*reset = (val & (1 << sc->resets[id].shift)) != 0 ? false : true;
mtx_unlock(&sc->mtx);
return (0);
}
static void
aw_ccung_device_lock(device_t dev)
{
struct aw_ccung_softc *sc;
sc = device_get_softc(dev);
mtx_lock(&sc->mtx);
}
static void
aw_ccung_device_unlock(device_t dev)
{
struct aw_ccung_softc *sc;
sc = device_get_softc(dev);
mtx_unlock(&sc->mtx);
}
static int
aw_ccung_probe(device_t dev)
{
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (ofw_bus_search_compatible(dev, compat_data)->ocd_data == 0)
return (ENXIO);
device_set_desc(dev, "Allwinner Clock Control Unit NG");
return (BUS_PROBE_DEFAULT);
}
static int
aw_ccung_register_gates(struct aw_ccung_softc *sc)
{
struct clk_gate_def def;
int i;
for (i = 0; i < sc->ngates; i++) {
if (sc->gates[i].name == NULL)
continue;
memset(&def, 0, sizeof(def));
def.clkdef.id = i;
def.clkdef.name = sc->gates[i].name;
def.clkdef.parent_names = &sc->gates[i].parent_name;
def.clkdef.parent_cnt = 1;
def.offset = sc->gates[i].offset;
def.shift = sc->gates[i].shift;
def.mask = 1;
def.on_value = 1;
def.off_value = 0;
clknode_gate_register(sc->clkdom, &def);
}
return (0);
}
static void
aw_ccung_init_clocks(struct aw_ccung_softc *sc)
{
struct clknode *clknode;
int i, error;
for (i = 0; i < sc->n_clk_init; i++) {
clknode = clknode_find_by_name(sc->clk_init[i].name);
if (clknode == NULL) {
device_printf(sc->dev, "Cannot find clock %s\n",
sc->clk_init[i].name);
continue;
}
if (sc->clk_init[i].parent_name != NULL) {
if (bootverbose)
device_printf(sc->dev, "Setting %s as parent for %s\n",
sc->clk_init[i].parent_name,
sc->clk_init[i].name);
error = clknode_set_parent_by_name(clknode,
sc->clk_init[i].parent_name);
if (error != 0) {
device_printf(sc->dev,
"Cannot set parent to %s for %s\n",
sc->clk_init[i].parent_name,
sc->clk_init[i].name);
continue;
}
}
if (sc->clk_init[i].default_freq != 0) {
error = clknode_set_freq(clknode,
sc->clk_init[i].default_freq, 0 , 0);
if (error != 0) {
device_printf(sc->dev,
"Cannot set frequency for %s to %llu\n",
sc->clk_init[i].name,
sc->clk_init[i].default_freq);
continue;
}
}
if (sc->clk_init[i].enable) {
error = clknode_enable(clknode);
if (error != 0) {
device_printf(sc->dev,
"Cannot enable %s\n",
sc->clk_init[i].name);
continue;
}
}
}
}
static int
aw_ccung_attach(device_t dev)
{
struct aw_ccung_softc *sc;
sc = device_get_softc(dev);
sc->dev = dev;
if (bus_alloc_resources(dev, aw_ccung_spec, &sc->res) != 0) {
device_printf(dev, "cannot allocate resources for device\n");
return (ENXIO);
}
mtx_init(&sc->mtx, device_get_nameunit(dev), NULL, MTX_DEF);
sc->type = ofw_bus_search_compatible(dev, compat_data)->ocd_data;
sc->clkdom = clkdom_create(dev);
if (sc->clkdom == NULL)
panic("Cannot create clkdom\n");
switch (sc->type) {
#if defined(SOC_ALLWINNER_H3)
case H3_CCU:
ccu_h3_register_clocks(sc);
break;
#endif
#if defined(SOC_ALLWINNER_A31)
case A31_CCU:
ccu_a31_register_clocks(sc);
break;
#endif
}
if (sc->gates)
aw_ccung_register_gates(sc);
if (clkdom_finit(sc->clkdom) != 0)
panic("cannot finalize clkdom initialization\n");
clkdom_xlock(sc->clkdom);
aw_ccung_init_clocks(sc);
clkdom_unlock(sc->clkdom);
if (bootverbose)
clkdom_dump(sc->clkdom);
/* If we have resets, register our self as a reset provider */
if (sc->resets)
hwreset_register_ofw_provider(dev);
return (0);
}
static device_method_t aw_ccung_methods[] = {
/* Device interface */
DEVMETHOD(device_probe, aw_ccung_probe),
DEVMETHOD(device_attach, aw_ccung_attach),
/* clkdev interface */
DEVMETHOD(clkdev_write_4, aw_ccung_write_4),
DEVMETHOD(clkdev_read_4, aw_ccung_read_4),
DEVMETHOD(clkdev_modify_4, aw_ccung_modify_4),
DEVMETHOD(clkdev_device_lock, aw_ccung_device_lock),
DEVMETHOD(clkdev_device_unlock, aw_ccung_device_unlock),
/* Reset interface */
DEVMETHOD(hwreset_assert, aw_ccung_reset_assert),
DEVMETHOD(hwreset_is_asserted, aw_ccung_reset_is_asserted),
DEVMETHOD_END
};
static driver_t aw_ccung_driver = {
"aw_ccung",
aw_ccung_methods,
sizeof(struct aw_ccung_softc),
};
static devclass_t aw_ccung_devclass;
EARLY_DRIVER_MODULE(aw_ccung, simplebus, aw_ccung_driver, aw_ccung_devclass,
0, 0, BUS_PASS_BUS + BUS_PASS_ORDER_MIDDLE);
MODULE_VERSION(aw_ccung, 1);

View File

@ -0,0 +1,59 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __CCU_NG_H__
#define __CCU_NG_H__
struct aw_ccung_softc {
device_t dev;
struct resource *res;
struct clkdom *clkdom;
struct mtx mtx;
int type;
struct aw_ccung_reset *resets;
int nresets;
struct aw_ccung_gate *gates;
int ngates;
struct aw_clk_init *clk_init;
int n_clk_init;
};
struct aw_ccung_reset {
uint32_t offset;
uint32_t shift;
};
struct aw_ccung_gate {
const char *name;
const char *parent_name;
uint32_t id;
uint32_t offset;
uint32_t shift;
};
#endif /* __CCU_NG_H__ */

View File

@ -0,0 +1,442 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AW_CLK_H__
#define __AW_CLK_H__
/*
Allwinner clocks formula :
PLLs:
(24MHz*N*K)/(M*P)
(24MHz*N)/(M*P)
(24MHz*N*2)/M
(24MHz*N)/M
(24MHz*N*K)/M
(24MHz*N*K/2)
(24MHz*N)/M
(24MHz*N*K/2)
(24MHz*N)/M
Periph clocks:
Clock Source/Divider N/Divider M
Clock Source/Divider N/Divider M/2
*/
struct aw_clk_init {
const char *name;
const char *parent_name;
uint64_t default_freq;
bool enable;
};
#define AW_CLK_HAS_GATE 0x0001
#define AW_CLK_HAS_LOCK 0x0002
#define AW_CLK_HAS_MUX 0x0004
#define AW_CLK_REPARENT 0x0008
#define AW_CLK_SCALE_CHANGE 0x0010
#define AW_CLK_HAS_FRAC 0x0020
#define AW_CLK_HAS_UPDATE 0x0040
#define AW_CLK_FACTOR_POWER_OF_TWO 0x0001
#define AW_CLK_FACTOR_ZERO_BASED 0x0002
#define AW_CLK_FACTOR_HAS_COND 0x0004
#define AW_CLK_FACTOR_FIXED 0x0008
struct aw_clk_factor {
uint32_t shift; /* Shift bits for the factor */
uint32_t mask; /* Mask to get the factor, will be override by the clk methods */
uint32_t width; /* Number of bits for the factor */
uint32_t value; /* Fixed value, depends on AW_CLK_FACTOR_FIXED */
uint32_t cond_shift;
uint32_t cond_mask;
uint32_t cond_width;
uint32_t cond_value;
uint32_t flags; /* Flags */
};
struct aw_clk_frac {
uint64_t freq0;
uint64_t freq1;
uint32_t mode_sel;
uint32_t freq_sel;
};
static inline uint32_t
aw_clk_get_factor(uint32_t val, struct aw_clk_factor *factor)
{
uint32_t factor_val;
uint32_t cond;
if (factor->flags & AW_CLK_FACTOR_HAS_COND) {
cond = (val & factor->cond_mask) >> factor->cond_shift;
if (cond != factor->cond_value)
return (1);
}
if (factor->flags & AW_CLK_FACTOR_FIXED)
return (factor->value);
factor_val = (val & factor->mask) >> factor->shift;
if (!(factor->flags & AW_CLK_FACTOR_ZERO_BASED))
factor_val += 1;
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
factor_val = 1 << factor_val;
return (factor_val);
}
static inline uint32_t
aw_clk_factor_get_max(struct aw_clk_factor *factor)
{
uint32_t max;
if (factor->flags & AW_CLK_FACTOR_FIXED)
max = factor->value;
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO)
max = 1 << ((1 << factor->width) - 1);
else {
max = (1 << factor->width);
}
return (max);
}
static inline uint32_t
aw_clk_factor_get_min(struct aw_clk_factor *factor)
{
uint32_t min;
if (factor->flags & AW_CLK_FACTOR_FIXED)
min = factor->value;
else if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
min = 0;
else
min = 1;
return (min);
}
static inline uint32_t
aw_clk_factor_get_value(struct aw_clk_factor *factor, uint32_t raw)
{
uint32_t val;
if (factor->flags & AW_CLK_FACTOR_FIXED)
return (factor->value);
if (factor->flags & AW_CLK_FACTOR_ZERO_BASED)
val = raw;
else if (factor->flags & AW_CLK_FACTOR_POWER_OF_TWO) {
for (val = 0; raw != 1; val++)
raw >>= 1;
} else
val = raw - 1;
return (val);
}
#define CCU_RESET(idx, o, s) \
[idx] = { \
.offset = o, \
.shift = s, \
},
#define CCU_GATE(idx, clkname, pname, o, s) \
[idx] = { \
.name = clkname, \
.parent_name = pname, \
.offset = o, \
.shift = s, \
},
#define NKMP_CLK(_clkname, _id, _name, _pnames, \
_offset, \
_n_shift, _n_width, _n_value, _n_flags, \
_k_shift, _k_width, _k_value, _k_flags, \
_m_shift, _m_width, _m_value, _m_flags, \
_p_shift, _p_width, _p_value, _p_flags, \
_gate, \
_lock, _lock_retries, \
_flags) \
static struct aw_clk_nkmp_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _n_shift, \
.n.width = _n_width, \
.n.value = _n_value, \
.n.flags = _n_flags, \
.k.shift = _k_shift, \
.k.width = _k_width, \
.k.value = _k_value, \
.k.flags = _k_flags, \
.m.shift = _m_shift, \
.m.width = _m_width, \
.m.value = _m_value, \
.m.flags = _m_flags, \
.p.shift = _p_shift, \
.p.width = _p_width, \
.p.value = _p_value, \
.p.flags = _p_flags, \
.gate_shift = _gate, \
.lock_shift = _lock, \
.lock_retries = _lock_retries, \
.flags = _flags, \
}
#define NKMP_CLK_WITH_MUX(_clkname, \
_id, _name, _pnames, \
_offset, \
_n_shift, _n_width, _n_value, _n_flags, \
_k_shift, _k_width, _k_value, _k_flags, \
_m_shift, _m_width, _m_value, _m_flags, \
_p_shift, _p_width, _p_value, _p_flags, \
_mux_shift, _mux_width, _gate, \
_lock, _lock_retries, \
_flags) \
static struct aw_clk_nkmp_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _n_shift, \
.n.width = _n_width, \
.n.value = _n_value, \
.n.flags = _n_flags, \
.k.shift = _k_shift, \
.k.width = _k_width, \
.k.value = _k_value, \
.k.flags = _k_flags, \
.m.shift = _m_shift, \
.m.width = _m_width, \
.m.value = _m_value, \
.m.flags = _m_flags, \
.p.shift = _p_shift, \
.p.width = _p_width, \
.p.value = _p_value, \
.p.flags = _p_flags, \
.mux_shift = _mux_shift, \
.mux_width = _mux_width, \
.gate_shift = _gate, \
.lock_shift = _lock, \
.lock_retries = _lock_retries, \
.flags = _flags, \
}
#define NKMP_CLK_WITH_UPDATE(_clkname, \
_id, _name, _pnames, \
_offset, \
_n_shift, _n_width, _n_value, _n_flags, \
_k_shift, _k_width, _k_value, _k_flags, \
_m_shift, _m_width, _m_value, _m_flags, \
_p_shift, _p_width, _p_value, _p_flags, \
_gate, \
_lock, _lock_retries, \
_update, \
_flags) \
static struct aw_clk_nkmp_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _n_shift, \
.n.width = _n_width, \
.n.value = _n_value, \
.n.flags = _n_flags, \
.k.shift = _k_shift, \
.k.width = _k_width, \
.k.value = _k_value, \
.k.flags = _k_flags, \
.m.shift = _m_shift, \
.m.width = _m_width, \
.m.value = _m_value, \
.m.flags = _m_flags, \
.p.shift = _p_shift, \
.p.width = _p_width, \
.p.value = _p_value, \
.p.flags = _p_flags, \
.gate_shift = _gate, \
.lock_shift = _lock, \
.lock_retries = _lock_retries, \
.update_shift = _update, \
.flags = _flags | AW_CLK_HAS_UPDATE, \
}
#define NM_CLK(_clkname, _id, _name, _pnames, \
_offset, \
_nshift, _nwidth, _nvalue, _nflags, \
_mshift, _mwidth, _mvalue, _mflags, \
_mux_shift, _mux_width, \
_gate_shift, \
_flags) \
static struct aw_clk_nm_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _nshift, \
.n.width = _nwidth, \
.n.value = _nvalue, \
.n.flags = _nflags, \
.mux_shift = _mux_shift, \
.m.shift = _mshift, \
.m.width = _mwidth, \
.m.value = _mvalue, \
.m.flags = _mflags, \
.mux_width = _mux_width, \
.flags = _flags, \
}
#define NM_CLK_WITH_FRAC(_clkname, _id, _name, _pnames, \
_offset, \
_nshift, _nwidth, _nvalue, _nflags, \
_mshift, _mwidth, _mvalue, _mflags, \
_gate_shift, _lock_shift,_lock_retries, \
_flags, _freq0, _freq1, _mode_sel, _freq_sel) \
static struct aw_clk_nm_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.n.shift = _nshift, \
.n.width = _nwidth, \
.n.value = _nvalue, \
.n.flags = _nflags, \
.m.shift = _mshift, \
.m.width = _mwidth, \
.m.value = _mvalue, \
.m.flags = _mflags, \
.gate_shift = _gate_shift, \
.lock_shift = _lock_shift, \
.lock_retries = _lock_retries, \
.flags = _flags | AW_CLK_HAS_FRAC, \
.frac.freq0 = _freq0, \
.frac.freq1 = _freq1, \
.frac.mode_sel = _mode_sel, \
.frac.freq_sel = _freq_sel, \
}
#define PREDIV_CLK(_clkname, _id, _name, _pnames, \
_offset, \
_mux_shift, _mux_width, \
_div_shift, _div_width, _div_value, _div_flags, \
_prediv_shift, _prediv_width, _prediv_value, _prediv_flags, \
_prediv_cond_shift, _prediv_cond_width, _prediv_cond_value) \
static struct aw_clk_prediv_mux_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames), \
}, \
.offset = _offset, \
.mux_shift = _mux_shift, \
.mux_width = _mux_width, \
.div.shift = _div_shift, \
.div.width = _div_width, \
.div.value = _div_value, \
.div.flags = _div_flags, \
.prediv.shift = _prediv_shift, \
.prediv.width = _prediv_width, \
.prediv.value = _prediv_value, \
.prediv.flags = _prediv_flags, \
.prediv.cond_shift = _prediv_cond_shift, \
.prediv.cond_width = _prediv_cond_width, \
.prediv.cond_value = _prediv_cond_value, \
}
#define MUX_CLK(_clkname, _id, _name, _pnames, \
_offset, _shift, _width) \
static struct clk_mux_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames) \
}, \
.offset = _offset, \
.shift = _shift, \
.width = _width, \
}
#define DIV_CLK(_clkname, _id, _name, _pnames, \
_offset, \
_i_shift, _i_width, \
_div_flags, _div_table) \
static struct clk_div_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = nitems(_pnames) \
}, \
.offset = _offset, \
.i_shift = _i_shift, \
.i_width = _i_width, \
.div_flags = _div_flags, \
.div_table = _div_table, \
}
#define FIXED_CLK(_clkname, _id, _name, _pnames, \
_freq, _mult, _div, _flags) \
static struct clk_fixed_def _clkname = { \
.clkdef = { \
.id = _id, \
.name = _name, \
.parent_names = _pnames, \
.parent_cnt = 1, \
}, \
.freq = _freq, \
.mult = _mult, \
.div = _div, \
.fixed_flags = _flags, \
}
#endif /* __AW_CLK_H__ */

View File

@ -0,0 +1,413 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <dev/extres/clk/clk.h>
#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
#include "clkdev_if.h"
/*
* clknode for clocks matching the formula :
*
* clk = (clkin * n * k) / (m * p)
*
*/
struct aw_clk_nkmp_sc {
uint32_t offset;
struct aw_clk_factor n;
struct aw_clk_factor k;
struct aw_clk_factor m;
struct aw_clk_factor p;
uint32_t mux_shift;
uint32_t mux_mask;
uint32_t gate_shift;
uint32_t lock_shift;
uint32_t lock_retries;
uint32_t update_shift;
uint32_t flags;
};
#define WRITE4(_clk, off, val) \
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
#define READ4(_clk, off, val) \
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define MODIFY4(_clk, off, clr, set ) \
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
#define DEVICE_LOCK(_clk) \
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
#define DEVICE_UNLOCK(_clk) \
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int
aw_clk_nkmp_init(struct clknode *clk, device_t dev)
{
struct aw_clk_nkmp_sc *sc;
uint32_t val, idx;
sc = clknode_get_softc(clk);
idx = 0;
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
idx = (val & sc->mux_mask) >> sc->mux_shift;
}
clknode_init_parent_idx(clk, idx);
return (0);
}
static int
aw_clk_nkmp_set_gate(struct clknode *clk, bool enable)
{
struct aw_clk_nkmp_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
if ((sc->flags & AW_CLK_HAS_GATE) == 0)
return (0);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
if (enable)
val |= (1 << sc->gate_shift);
else
val &= ~(1 << sc->gate_shift);
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static int
aw_clk_nkmp_set_mux(struct clknode *clk, int index)
{
struct aw_clk_nkmp_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
if ((sc->flags & AW_CLK_HAS_MUX) != 0)
return (0);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~(sc->mux_mask >> sc->mux_shift);
val |= index << sc->mux_shift;
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static uint64_t
aw_clk_nkmp_find_best(struct aw_clk_nkmp_sc *sc, uint64_t fparent, uint64_t *fout,
uint32_t *factor_n, uint32_t *factor_k, uint32_t *factor_m, uint32_t *factor_p)
{
uint64_t cur, best;
uint32_t n, k, m, p;
best = 0;
*factor_n = 0;
*factor_k = 0;
*factor_m = 0;
*factor_p = 0;
for (n = aw_clk_factor_get_min(&sc->n); n <= aw_clk_factor_get_max(&sc->n); ) {
for (k = aw_clk_factor_get_min(&sc->k); k <= aw_clk_factor_get_max(&sc->k); ) {
for (m = aw_clk_factor_get_min(&sc->m); m <= aw_clk_factor_get_max(&sc->m); ) {
for (p = aw_clk_factor_get_min(&sc->p); p <= aw_clk_factor_get_max(&sc->p); ) {
cur = (fparent * n * k) / (m * p);
if ((*fout - cur) < (*fout - best)) {
best = cur;
*factor_n = n;
*factor_k = k;
*factor_m = m;
*factor_p = p;
}
if (best == *fout)
return (best);
if ((sc->p.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
p <<= 1;
else
p++;
}
if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
m <<= 1;
else
m++;
}
if ((sc->k.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
k <<= 1;
else
k++;
}
if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
n <<= 1;
else
n++;
}
return best;
}
static void
aw_clk_nkmp_set_freq_scale(struct clknode *clk, struct aw_clk_nkmp_sc *sc,
uint32_t factor_n, uint32_t factor_k, uint32_t factor_m, uint32_t factor_p)
{
uint32_t val, n, k, m, p;
int retry;
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
n = aw_clk_get_factor(val, &sc->n);
k = aw_clk_get_factor(val, &sc->k);
m = aw_clk_get_factor(val, &sc->m);
p = aw_clk_get_factor(val, &sc->p);
if (p < factor_p) {
val &= ~sc->p.mask;
val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
}
if (m < factor_m) {
val &= ~sc->m.mask;
val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
}
val &= ~sc->n.mask;
val &= ~sc->k.mask;
val |= aw_clk_factor_get_value(&sc->n, factor_n) << sc->n.shift;
val |= aw_clk_factor_get_value(&sc->k, factor_k) << sc->k.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
if (m > factor_m) {
val &= ~sc->m.mask;
val |= aw_clk_factor_get_value(&sc->m, factor_m) << sc->m.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
}
if (p > factor_p) {
val &= ~sc->p.mask;
val |= aw_clk_factor_get_value(&sc->p, factor_p) << sc->p.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
}
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
for (retry = 0; retry < sc->lock_retries; retry++) {
READ4(clk, sc->offset, &val);
if ((val & (1 << sc->lock_shift)) != 0)
break;
DELAY(1000);
}
}
DEVICE_UNLOCK(clk);
}
static int
aw_clk_nkmp_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
int flags, int *stop)
{
struct aw_clk_nkmp_sc *sc;
uint64_t best;
uint32_t val, best_n, best_k, best_m, best_p;
int retry;
sc = clknode_get_softc(clk);
best = aw_clk_nkmp_find_best(sc, fparent, fout,
&best_n, &best_k, &best_m, &best_p);
if ((flags & CLK_SET_DRYRUN) != 0) {
*fout = best;
*stop = 1;
return (0);
}
if ((best < *fout) &&
((flags & CLK_SET_ROUND_DOWN) != 0)) {
*stop = 1;
return (ERANGE);
}
if ((best > *fout) &&
((flags & CLK_SET_ROUND_UP) != 0)) {
*stop = 1;
return (ERANGE);
}
if ((sc->flags & AW_CLK_SCALE_CHANGE) != 0)
aw_clk_nkmp_set_freq_scale(clk, sc,
best_n, best_k, best_m, best_p);
else {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~sc->n.mask;
val &= ~sc->k.mask;
val &= ~sc->m.mask;
val &= ~sc->p.mask;
val |= aw_clk_factor_get_value(&sc->n, best_n) << sc->n.shift;
val |= aw_clk_factor_get_value(&sc->k, best_k) << sc->k.shift;
val |= aw_clk_factor_get_value(&sc->m, best_m) << sc->m.shift;
val |= aw_clk_factor_get_value(&sc->p, best_p) << sc->p.shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
if ((sc->flags & AW_CLK_HAS_UPDATE) != 0) {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val |= 1 << sc->update_shift;
WRITE4(clk, sc->offset, val);
DELAY(2000);
}
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
for (retry = 0; retry < sc->lock_retries; retry++) {
READ4(clk, sc->offset, &val);
if ((val & (1 << sc->lock_shift)) != 0)
break;
DELAY(1000);
}
}
}
*fout = best;
*stop = 1;
return (0);
}
static int
aw_clk_nkmp_recalc(struct clknode *clk, uint64_t *freq)
{
struct aw_clk_nkmp_sc *sc;
uint32_t val, m, n, k, p;
sc = clknode_get_softc(clk);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
n = aw_clk_get_factor(val, &sc->n);
k = aw_clk_get_factor(val, &sc->k);
m = aw_clk_get_factor(val, &sc->m);
p = aw_clk_get_factor(val, &sc->p);
*freq = (*freq * n * k) / (m * p);
return (0);
}
static clknode_method_t aw_nkmp_clknode_methods[] = {
/* Device interface */
CLKNODEMETHOD(clknode_init, aw_clk_nkmp_init),
CLKNODEMETHOD(clknode_set_gate, aw_clk_nkmp_set_gate),
CLKNODEMETHOD(clknode_set_mux, aw_clk_nkmp_set_mux),
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nkmp_recalc),
CLKNODEMETHOD(clknode_set_freq, aw_clk_nkmp_set_freq),
CLKNODEMETHOD_END
};
DEFINE_CLASS_1(aw_nkmp_clknode, aw_nkmp_clknode_class, aw_nkmp_clknode_methods,
sizeof(struct aw_clk_nkmp_sc), clknode_class);
int
aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef)
{
struct clknode *clk;
struct aw_clk_nkmp_sc *sc;
clk = clknode_create(clkdom, &aw_nkmp_clknode_class, &clkdef->clkdef);
if (clk == NULL)
return (1);
sc = clknode_get_softc(clk);
sc->offset = clkdef->offset;
sc->n.shift = clkdef->n.shift;
sc->n.width = clkdef->n.width;
sc->n.mask = ((1 << clkdef->n.width) - 1) << sc->n.shift;
sc->n.value = clkdef->n.value;
sc->n.flags = clkdef->n.flags;
sc->k.shift = clkdef->k.shift;
sc->k.width = clkdef->k.width;
sc->k.mask = ((1 << clkdef->k.width) - 1) << sc->k.shift;
sc->k.value = clkdef->k.value;
sc->k.flags = clkdef->k.flags;
sc->m.shift = clkdef->m.shift;
sc->m.width = clkdef->m.width;
sc->m.mask = ((1 << clkdef->m.width) - 1) << sc->m.shift;
sc->m.value = clkdef->m.value;
sc->m.flags = clkdef->m.flags;
sc->p.shift = clkdef->p.shift;
sc->p.width = clkdef->p.width;
sc->p.mask = ((1 << clkdef->p.width) - 1) << sc->p.shift;
sc->p.value = clkdef->p.value;
sc->p.flags = clkdef->p.flags;
sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
sc->gate_shift = clkdef->gate_shift;
sc->lock_shift = clkdef->lock_shift;
sc->lock_retries = clkdef->lock_retries;
sc->update_shift = clkdef->update_shift;
sc->flags = clkdef->flags;
clknode_register(clkdom, clk);
return (0);
}

View File

@ -0,0 +1,56 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __AW_CLK_NKMP_H__
#define __AW_CLK_NKMP_H__
#include <arm/allwinner/clkng/aw_clk.h>
struct aw_clk_nkmp_def {
struct clknode_init_def clkdef;
uint32_t offset;
struct aw_clk_factor m;
struct aw_clk_factor k;
struct aw_clk_factor n;
struct aw_clk_factor p;
uint32_t mux_shift;
uint32_t mux_width;
uint32_t gate_shift;
uint32_t lock_shift;
uint32_t lock_retries;
uint32_t update_shift;
uint32_t flags;
};
int aw_clk_nkmp_register(struct clkdom *clkdom, struct aw_clk_nkmp_def *clkdef);
#endif /* __AW_CLK_NKMP_H__ */

View File

@ -0,0 +1,361 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <dev/extres/clk/clk.h>
#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_nm.h>
#include "clkdev_if.h"
/*
* clknode for clocks matching the formula :
*
* clk = clkin / n / m
*
*/
struct aw_clk_nm_sc {
uint32_t offset;
struct aw_clk_factor m;
struct aw_clk_factor n;
struct aw_clk_frac frac;
uint32_t mux_shift;
uint32_t mux_mask;
uint32_t gate_shift;
uint32_t lock_shift;
uint32_t lock_retries;
uint32_t flags;
};
#define WRITE4(_clk, off, val) \
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
#define READ4(_clk, off, val) \
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define DEVICE_LOCK(_clk) \
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
#define DEVICE_UNLOCK(_clk) \
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int
aw_clk_nm_init(struct clknode *clk, device_t dev)
{
struct aw_clk_nm_sc *sc;
uint32_t val, idx;
sc = clknode_get_softc(clk);
idx = 0;
if ((sc->flags & AW_CLK_HAS_MUX) != 0) {
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
idx = (val & sc->mux_mask) >> sc->mux_shift;
}
clknode_init_parent_idx(clk, idx);
return (0);
}
static int
aw_clk_nm_set_gate(struct clknode *clk, bool enable)
{
struct aw_clk_nm_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
if ((sc->flags & AW_CLK_HAS_GATE) == 0)
return (0);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
if (enable)
val |= (1 << sc->gate_shift);
else
val &= ~(1 << sc->gate_shift);
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static int
aw_clk_nm_set_mux(struct clknode *clk, int index)
{
struct aw_clk_nm_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
if ((sc->flags & AW_CLK_HAS_MUX) != 0)
return (0);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~(sc->mux_mask >> sc->mux_shift);
val |= index << sc->mux_shift;
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static uint64_t
aw_clk_nm_find_best(struct aw_clk_nm_sc *sc, uint64_t fparent, uint64_t *fout,
uint32_t *factor_n, uint32_t *factor_m)
{
uint64_t cur, best;
uint32_t m, n, max_m, max_n, min_m, min_n;
*factor_n = *factor_m = 0;
max_m = aw_clk_factor_get_max(&sc->m);
max_n = aw_clk_factor_get_max(&sc->n);
min_m = aw_clk_factor_get_min(&sc->m);
min_n = aw_clk_factor_get_min(&sc->n);
for (m = min_m; m <= max_m; ) {
for (n = min_m; n <= max_n; ) {
cur = fparent / n / m;
if ((*fout - cur) < (*fout - best)) {
best = cur;
*factor_n = n;
*factor_m = m;
}
if ((sc->n.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
n <<= 1;
else
n++;
}
if ((sc->m.flags & AW_CLK_FACTOR_POWER_OF_TWO) != 0)
m <<= 1;
else
m++;
}
return (best);
}
static int
aw_clk_nm_set_freq(struct clknode *clk, uint64_t fparent, uint64_t *fout,
int flags, int *stop)
{
struct aw_clk_nm_sc *sc;
struct clknode *p_clk;
const char **p_names;
uint64_t cur, best, best_frac;
uint32_t val, m, n, best_m, best_n;
int p_idx, best_parent, retry;
sc = clknode_get_softc(clk);
best = best_frac = cur = 0;
best_parent = 0;
if ((sc->flags & AW_CLK_REPARENT) != 0) {
p_names = clknode_get_parent_names(clk);
for (p_idx = 0; p_idx != clknode_get_parents_num(clk); p_idx++) {
p_clk = clknode_find_by_name(p_names[p_idx]);
clknode_get_freq(p_clk, &fparent);
cur = aw_clk_nm_find_best(sc, fparent, fout, &n, &m);
if ((*fout - cur) < (*fout - best)) {
best = cur;
best_parent = p_idx;
best_n = n;
best_m = m;
}
}
p_idx = clknode_get_parent_idx(clk);
p_clk = clknode_get_parent(clk);
clknode_get_freq(p_clk, &fparent);
} else {
if (sc->flags & AW_CLK_HAS_FRAC &&
(*fout == sc->frac.freq0 || *fout == sc->frac.freq1))
best = best_frac = *fout;
if (best == 0)
best = aw_clk_nm_find_best(sc, fparent, fout,
&best_n, &best_m);
}
if ((flags & CLK_SET_DRYRUN) != 0) {
*fout = best;
*stop = 1;
return (0);
}
if ((best < *fout) &&
((flags & CLK_SET_ROUND_DOWN) == 0)) {
*stop = 1;
return (ERANGE);
}
if ((best > *fout) &&
((flags & CLK_SET_ROUND_UP) == 0)) {
*stop = 1;
return (ERANGE);
}
if (p_idx != best_parent)
clknode_set_parent_by_idx(clk, best_parent);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
if (best_frac != 0) {
val &= ~sc->frac.mode_sel;
if (best_frac == sc->frac.freq0)
val &= ~sc->frac.freq_sel;
else
val |= sc->frac.freq_sel;
} else {
n = aw_clk_factor_get_value(&sc->n, best_n);
m = aw_clk_factor_get_value(&sc->m, best_m);
val &= ~sc->n.mask;
val &= ~sc->m.mask;
val |= n << sc->n.shift;
val |= m << sc->m.shift;
}
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
if ((sc->flags & AW_CLK_HAS_LOCK) != 0) {
for (retry = 0; retry < sc->lock_retries; retry++) {
READ4(clk, sc->offset, &val);
if ((val & (1 << sc->lock_shift)) != 0)
break;
DELAY(1000);
}
}
*fout = best;
*stop = 1;
return (0);
}
static int
aw_clk_nm_recalc(struct clknode *clk, uint64_t *freq)
{
struct aw_clk_nm_sc *sc;
uint32_t val, m, n;
sc = clknode_get_softc(clk);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
if (sc->flags & AW_CLK_HAS_FRAC && ((val & sc->frac.mode_sel) == 0)) {
if (val & sc->frac.freq_sel)
*freq = sc->frac.freq1;
else
*freq = sc->frac.freq0;
} else {
m = aw_clk_get_factor(val, &sc->m);
n = aw_clk_get_factor(val, &sc->n);
*freq = *freq / n / m;
}
return (0);
}
static clknode_method_t aw_nm_clknode_methods[] = {
/* Device interface */
CLKNODEMETHOD(clknode_init, aw_clk_nm_init),
CLKNODEMETHOD(clknode_set_gate, aw_clk_nm_set_gate),
CLKNODEMETHOD(clknode_set_mux, aw_clk_nm_set_mux),
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_nm_recalc),
CLKNODEMETHOD(clknode_set_freq, aw_clk_nm_set_freq),
CLKNODEMETHOD_END
};
DEFINE_CLASS_1(aw_nm_clknode, aw_nm_clknode_class, aw_nm_clknode_methods,
sizeof(struct aw_clk_nm_sc), clknode_class);
int
aw_clk_nm_register(struct clkdom *clkdom, struct aw_clk_nm_def *clkdef)
{
struct clknode *clk;
struct aw_clk_nm_sc *sc;
clk = clknode_create(clkdom, &aw_nm_clknode_class, &clkdef->clkdef);
if (clk == NULL)
return (1);
sc = clknode_get_softc(clk);
sc->offset = clkdef->offset;
sc->m.shift = clkdef->m.shift;
sc->m.width = clkdef->m.width;
sc->m.mask = ((1 << sc->m.width) - 1) << sc->m.shift;
sc->m.value = clkdef->m.value;
sc->m.flags = clkdef->m.flags;
sc->n.shift = clkdef->n.shift;
sc->n.width = clkdef->n.width;
sc->n.mask = ((1 << sc->n.width) - 1) << sc->n.shift;
sc->n.value = clkdef->n.value;
sc->n.flags = clkdef->n.flags;
sc->frac.freq0 = clkdef->frac.freq0;
sc->frac.freq1 = clkdef->frac.freq1;
sc->frac.mode_sel = 1 << clkdef->frac.mode_sel;
sc->frac.freq_sel = 1 << clkdef->frac.freq_sel;
sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
sc->gate_shift = clkdef->gate_shift;
sc->lock_shift = clkdef->lock_shift;
sc->lock_retries = clkdef->lock_retries;
sc->flags = clkdef->flags;
clknode_register(clkdom, clk);
return (0);
}

View File

@ -1,6 +1,5 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994 Christos Zoulas
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -11,31 +10,44 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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.
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_ULIMIT_H_
#define _SVR4_ULIMIT_H_
#ifndef __AW_CLK_NM_H__
#define __AW_CLK_NM_H__
#define SVR4_GFILLIM 1
#define SVR4_SFILLIM 2
#define SVR4_GMEMLIM 3
#define SVR4_GDESLIM 4
#define SVR4_GTXTOFF 64
#include <dev/extres/clk/clk.h>
struct aw_clk_nm_def {
struct clknode_init_def clkdef;
uint32_t offset;
#endif /* !_SVR4_ULIMIT_H_ */
struct aw_clk_factor m;
struct aw_clk_factor n;
struct aw_clk_frac frac;
uint32_t mux_shift;
uint32_t mux_width;
uint32_t gate_shift;
uint32_t lock_shift;
uint32_t lock_retries;
uint32_t flags;
};
int aw_clk_nm_register(struct clkdom *clkdom, struct aw_clk_nm_def *clkdef);
#endif /* __AW_CLK_NM_H__ */

View File

@ -0,0 +1,169 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <dev/extres/clk/clk.h>
#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
#include "clkdev_if.h"
/*
* clknode for clocks matching the formula :
*
* clk = clkin / prediv / div
*
* and where prediv is conditional
*
*/
struct aw_clk_prediv_mux_sc {
uint32_t offset;
uint32_t mux_shift;
uint32_t mux_mask;
struct aw_clk_factor div;
struct aw_clk_factor prediv;
uint32_t flags;
};
#define WRITE4(_clk, off, val) \
CLKDEV_WRITE_4(clknode_get_device(_clk), off, val)
#define READ4(_clk, off, val) \
CLKDEV_READ_4(clknode_get_device(_clk), off, val)
#define MODIFY4(_clk, off, clr, set ) \
CLKDEV_MODIFY_4(clknode_get_device(_clk), off, clr, set)
#define DEVICE_LOCK(_clk) \
CLKDEV_DEVICE_LOCK(clknode_get_device(_clk))
#define DEVICE_UNLOCK(_clk) \
CLKDEV_DEVICE_UNLOCK(clknode_get_device(_clk))
static int
aw_clk_prediv_mux_init(struct clknode *clk, device_t dev)
{
clknode_init_parent_idx(clk, 0);
return (0);
}
static int
aw_clk_prediv_mux_set_mux(struct clknode *clk, int index)
{
struct aw_clk_prediv_mux_sc *sc;
uint32_t val;
sc = clknode_get_softc(clk);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
val &= ~sc->mux_mask;
val |= index << sc->mux_shift;
WRITE4(clk, sc->offset, val);
DEVICE_UNLOCK(clk);
return (0);
}
static int
aw_clk_prediv_mux_recalc(struct clknode *clk, uint64_t *freq)
{
struct aw_clk_prediv_mux_sc *sc;
uint32_t val, div, prediv;
sc = clknode_get_softc(clk);
DEVICE_LOCK(clk);
READ4(clk, sc->offset, &val);
DEVICE_UNLOCK(clk);
div = aw_clk_get_factor(val, &sc->div);
prediv = aw_clk_get_factor(val, &sc->prediv);
*freq = *freq / prediv / div;
return (0);
}
static clknode_method_t aw_prediv_mux_clknode_methods[] = {
/* Device interface */
CLKNODEMETHOD(clknode_init, aw_clk_prediv_mux_init),
CLKNODEMETHOD(clknode_set_mux, aw_clk_prediv_mux_set_mux),
CLKNODEMETHOD(clknode_recalc_freq, aw_clk_prediv_mux_recalc),
CLKNODEMETHOD_END
};
DEFINE_CLASS_1(aw_prediv_mux_clknode, aw_prediv_mux_clknode_class,
aw_prediv_mux_clknode_methods, sizeof(struct aw_clk_prediv_mux_sc),
clknode_class);
int
aw_clk_prediv_mux_register(struct clkdom *clkdom, struct aw_clk_prediv_mux_def *clkdef)
{
struct clknode *clk;
struct aw_clk_prediv_mux_sc *sc;
clk = clknode_create(clkdom, &aw_prediv_mux_clknode_class, &clkdef->clkdef);
if (clk == NULL)
return (1);
sc = clknode_get_softc(clk);
sc->offset = clkdef->offset;
sc->mux_shift = clkdef->mux_shift;
sc->mux_mask = ((1 << clkdef->mux_width) - 1) << sc->mux_shift;
sc->div.shift = clkdef->div.shift;
sc->div.mask = ((1 << clkdef->div.width) - 1) << sc->div.shift;
sc->div.value = clkdef->div.value;
sc->div.cond_shift = clkdef->div.cond_shift;
sc->div.cond_mask = ((1 << clkdef->div.cond_width) - 1) << sc->div.shift;
sc->div.cond_value = clkdef->div.cond_value;
sc->div.flags = clkdef->div.flags;
sc->prediv.shift = clkdef->prediv.shift;
sc->prediv.mask = ((1 << clkdef->prediv.width) - 1) << sc->prediv.shift;
sc->prediv.value = clkdef->prediv.value;
sc->prediv.cond_shift = clkdef->prediv.cond_shift;
sc->prediv.cond_mask = ((1 << clkdef->prediv.cond_width) - 1) << sc->prediv.shift;
sc->prediv.cond_value = clkdef->prediv.cond_value;
sc->prediv.flags = clkdef->prediv.flags;
sc->flags = clkdef->flags;
clknode_register(clkdom, clk);
return (0);
}

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
@ -10,30 +10,40 @@
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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.
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include "opt_svr4.h"
#ifndef __AW_CLK_PREDIV_MUX_H__
#define __AW_CLK_PREDIV_MUX_H__
#if !defined(_SVR4_H)
#define _SVR4_H
#include <arm/allwinner/clkng/aw_clk.h>
extern struct sysentvec svr4_sysvec;
struct aw_clk_prediv_mux_def {
struct clknode_init_def clkdef;
uint32_t offset;
#define COMPAT_SVR4_SOLARIS2
uint32_t mux_shift;
uint32_t mux_width;
#endif
struct aw_clk_factor div;
struct aw_clk_factor prediv;
uint32_t flags;
};
int aw_clk_prediv_mux_register(struct clkdom *clkdom, struct aw_clk_prediv_mux_def *clkdef);
#endif /* __AW_CLK_PREDIV_MUX_H__ */

View File

@ -0,0 +1,936 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <dev/extres/clk/clk_div.h>
#include <dev/extres/clk/clk_fixed.h>
#include <dev/extres/clk/clk_mux.h>
#include <arm/allwinner/clkng/aw_ccung.h>
#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_nm.h>
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
#include "ccu_a31.h"
static struct aw_ccung_reset a31_ccu_resets[] = {
CCU_RESET(A31_RST_USB_PHY0, 0xcc, 0)
CCU_RESET(A31_RST_USB_PHY1, 0xcc, 1)
CCU_RESET(A31_RST_USB_PHY2, 0xcc, 2)
CCU_RESET(A31_RST_AHB1_MIPI_DSI, 0x2c0, 1)
CCU_RESET(A31_RST_AHB1_SS, 0x2c0, 5)
CCU_RESET(A31_RST_AHB1_DMA, 0x2c0, 6)
CCU_RESET(A31_RST_AHB1_MMC0, 0x2c0, 8)
CCU_RESET(A31_RST_AHB1_MMC1, 0x2c0, 9)
CCU_RESET(A31_RST_AHB1_MMC2, 0x2c0, 10)
CCU_RESET(A31_RST_AHB1_MMC3, 0x2c0, 11)
CCU_RESET(A31_RST_AHB1_NAND1, 0x2c0, 12)
CCU_RESET(A31_RST_AHB1_NAND0, 0x2c0, 13)
CCU_RESET(A31_RST_AHB1_SDRAM, 0x2c0, 14)
CCU_RESET(A31_RST_AHB1_EMAC, 0x2c0, 17)
CCU_RESET(A31_RST_AHB1_TS, 0x2c0, 18)
CCU_RESET(A31_RST_AHB1_HSTIMER, 0x2c0, 19)
CCU_RESET(A31_RST_AHB1_SPI0, 0x2c0, 20)
CCU_RESET(A31_RST_AHB1_SPI1, 0x2c0, 21)
CCU_RESET(A31_RST_AHB1_SPI2, 0x2c0, 22)
CCU_RESET(A31_RST_AHB1_SPI3, 0x2c0, 23)
CCU_RESET(A31_RST_AHB1_OTG, 0x2c0, 24)
CCU_RESET(A31_RST_AHB1_EHCI0, 0x2c0, 26)
CCU_RESET(A31_RST_AHB1_EHCI1, 0x2c0, 27)
CCU_RESET(A31_RST_AHB1_OHCI0, 0x2c0, 29)
CCU_RESET(A31_RST_AHB1_OHCI1, 0x2c0, 30)
CCU_RESET(A31_RST_AHB1_OHCI2, 0x2c0, 31)
CCU_RESET(A31_RST_AHB1_VE, 0x2c4, 0)
CCU_RESET(A31_RST_AHB1_LCD0, 0x2c4, 4)
CCU_RESET(A31_RST_AHB1_LCD1, 0x2c4, 5)
CCU_RESET(A31_RST_AHB1_CSI, 0x2c4, 8)
CCU_RESET(A31_RST_AHB1_HDMI, 0x2c4, 11)
CCU_RESET(A31_RST_AHB1_BE0, 0x2c4, 12)
CCU_RESET(A31_RST_AHB1_BE1, 0x2c4, 13)
CCU_RESET(A31_RST_AHB1_FE0, 0x2c4, 14)
CCU_RESET(A31_RST_AHB1_FE1, 0x2c4, 15)
CCU_RESET(A31_RST_AHB1_MP, 0x2c4, 18)
CCU_RESET(A31_RST_AHB1_GPU, 0x2c4, 20)
CCU_RESET(A31_RST_AHB1_DEU0, 0x2c4, 23)
CCU_RESET(A31_RST_AHB1_DEU1, 0x2c4, 24)
CCU_RESET(A31_RST_AHB1_DRC0, 0x2c4, 25)
CCU_RESET(A31_RST_AHB1_DRC1, 0x2c4, 26)
CCU_RESET(A31_RST_AHB1_LVDS, 0x2c8, 0)
CCU_RESET(A31_RST_APB1_CODEC, 0x2d0, 0)
CCU_RESET(A31_RST_APB1_SPDIF, 0x2d0, 1)
CCU_RESET(A31_RST_APB1_DIGITAL_MIC, 0x2d0, 4)
CCU_RESET(A31_RST_APB1_DAUDIO0, 0x2d0, 12)
CCU_RESET(A31_RST_APB1_DAUDIO1, 0x2d0, 13)
CCU_RESET(A31_RST_APB2_I2C0, 0x2d8, 0)
CCU_RESET(A31_RST_APB2_I2C1, 0x2d8, 1)
CCU_RESET(A31_RST_APB2_I2C2, 0x2d8, 2)
CCU_RESET(A31_RST_APB2_I2C3, 0x2d8, 3)
CCU_RESET(A31_RST_APB2_UART0, 0x2d8, 16)
CCU_RESET(A31_RST_APB2_UART1, 0x2d8, 17)
CCU_RESET(A31_RST_APB2_UART2, 0x2d8, 18)
CCU_RESET(A31_RST_APB2_UART3, 0x2d8, 19)
CCU_RESET(A31_RST_APB2_UART4, 0x2d8, 20)
CCU_RESET(A31_RST_APB2_UART5, 0x2d8, 21)
};
static struct aw_ccung_gate a31_ccu_gates[] = {
CCU_GATE(A31_CLK_AHB1_MIPIDSI, "ahb1-mipidsi", "ahb1", 0x60, 1)
CCU_GATE(A31_CLK_AHB1_SS, "ahb1-ss", "ahb1", 0x60, 5)
CCU_GATE(A31_CLK_AHB1_DMA, "ahb1-dma", "ahb1", 0x60, 6)
CCU_GATE(A31_CLK_AHB1_MMC0, "ahb1-mmc0", "ahb1", 0x60, 8)
CCU_GATE(A31_CLK_AHB1_MMC1, "ahb1-mmc1", "ahb1", 0x60, 9)
CCU_GATE(A31_CLK_AHB1_MMC2, "ahb1-mmc2", "ahb1", 0x60, 10)
CCU_GATE(A31_CLK_AHB1_MMC3, "ahb1-mmc3", "ahb1", 0x60, 11)
CCU_GATE(A31_CLK_AHB1_NAND1, "ahb1-nand1", "ahb1", 0x60, 12)
CCU_GATE(A31_CLK_AHB1_NAND0, "ahb1-nand0", "ahb1", 0x60, 13)
CCU_GATE(A31_CLK_AHB1_SDRAM, "ahb1-sdram", "ahb1", 0x60, 14)
CCU_GATE(A31_CLK_AHB1_EMAC, "ahb1-emac", "ahb1", 0x60, 17)
CCU_GATE(A31_CLK_AHB1_TS, "ahb1-ts", "ahb1", 0x60, 18)
CCU_GATE(A31_CLK_AHB1_HSTIMER, "ahb1-hstimer", "ahb1", 0x60, 19)
CCU_GATE(A31_CLK_AHB1_SPI0, "ahb1-spi0", "ahb1", 0x60, 20)
CCU_GATE(A31_CLK_AHB1_SPI1, "ahb1-spi1", "ahb1", 0x60, 21)
CCU_GATE(A31_CLK_AHB1_SPI2, "ahb1-spi2", "ahb1", 0x60, 22)
CCU_GATE(A31_CLK_AHB1_SPI3, "ahb1-spi3", "ahb1", 0x60, 23)
CCU_GATE(A31_CLK_AHB1_OTG, "ahb1-otg", "ahb1", 0x60, 24)
CCU_GATE(A31_CLK_AHB1_EHCI0, "ahb1-ehci0", "ahb1", 0x60, 26)
CCU_GATE(A31_CLK_AHB1_EHCI1, "ahb1-ehci1", "ahb1", 0x60, 27)
CCU_GATE(A31_CLK_AHB1_OHCI0, "ahb1-ohci0", "ahb1", 0x60, 29)
CCU_GATE(A31_CLK_AHB1_OHCI1, "ahb1-ohci1", "ahb1", 0x60, 30)
CCU_GATE(A31_CLK_AHB1_OHCI2, "ahb1-ohci2", "ahb1", 0x60, 31)
CCU_GATE(A31_CLK_AHB1_VE, "ahb1-ve", "ahb1", 0x64, 0)
CCU_GATE(A31_CLK_AHB1_LCD0, "ahb1-lcd0", "ahb1", 0x64, 4)
CCU_GATE(A31_CLK_AHB1_LCD1, "ahb1-lcd1", "ahb1", 0x64, 5)
CCU_GATE(A31_CLK_AHB1_CSI, "ahb1-csi", "ahb1", 0x64, 8)
CCU_GATE(A31_CLK_AHB1_HDMI, "ahb1-hdmi", "ahb1", 0x64, 11)
CCU_GATE(A31_CLK_AHB1_BE0, "ahb1-be0", "ahb1", 0x64, 12)
CCU_GATE(A31_CLK_AHB1_BE1, "ahb1-be1", "ahb1", 0x64, 13)
CCU_GATE(A31_CLK_AHB1_FE0, "ahb1-fe0", "ahb1", 0x64, 14)
CCU_GATE(A31_CLK_AHB1_FE1, "ahb1-fe1", "ahb1", 0x64, 15)
CCU_GATE(A31_CLK_AHB1_MP, "ahb1-mp", "ahb1", 0x64, 18)
CCU_GATE(A31_CLK_AHB1_GPU, "ahb1-gpu", "ahb1", 0x64, 20)
CCU_GATE(A31_CLK_AHB1_DEU0, "ahb1-deu0", "ahb1", 0x64, 23)
CCU_GATE(A31_CLK_AHB1_DEU1, "ahb1-deu1", "ahb1", 0x64, 24)
CCU_GATE(A31_CLK_AHB1_DRC0, "ahb1-drc0", "ahb1", 0x64, 25)
CCU_GATE(A31_CLK_AHB1_DRC1, "ahb1-drc1", "ahb1", 0x64, 26)
CCU_GATE(A31_CLK_APB1_CODEC, "apb1-codec", "apb1", 0x68, 0)
CCU_GATE(A31_CLK_APB1_SPDIF, "apb1-spdif", "apb1", 0x68, 1)
CCU_GATE(A31_CLK_APB1_DIGITAL_MIC, "apb1-digital-mic", "apb1", 0x68, 4)
CCU_GATE(A31_CLK_APB1_PIO, "apb1-pio", "apb1", 0x68, 5)
CCU_GATE(A31_CLK_APB1_DAUDIO0, "apb1-daudio0", "apb1", 0x68, 12)
CCU_GATE(A31_CLK_APB1_DAUDIO1, "apb1-daudio1", "apb1", 0x68, 13)
CCU_GATE(A31_CLK_APB2_I2C0, "apb2-i2c0", "apb2", 0x6c, 0)
CCU_GATE(A31_CLK_APB2_I2C1, "apb2-i2c1", "apb2", 0x6c, 1)
CCU_GATE(A31_CLK_APB2_I2C2, "apb2-i2c2", "apb2", 0x6c, 2)
CCU_GATE(A31_CLK_APB2_I2C3, "apb2-i2c3", "apb2", 0x6c, 3)
CCU_GATE(A31_CLK_APB2_UART0, "apb2-uart0", "apb2", 0x6c, 16)
CCU_GATE(A31_CLK_APB2_UART1, "apb2-uart1", "apb2", 0x6c, 17)
CCU_GATE(A31_CLK_APB2_UART2, "apb2-uart2", "apb2", 0x6c, 18)
CCU_GATE(A31_CLK_APB2_UART3, "apb2-uart3", "apb2", 0x6c, 19)
CCU_GATE(A31_CLK_APB2_UART4, "apb2-uart4", "apb2", 0x6c, 20)
CCU_GATE(A31_CLK_APB2_UART5, "apb2-uart5", "apb2", 0x6c, 21)
CCU_GATE(A31_CLK_DAUDIO0, "daudio0", "daudio0mux", 0xb0, 31)
CCU_GATE(A31_CLK_DAUDIO1, "daudio1", "daudio1mux", 0xb4, 31)
CCU_GATE(A31_CLK_USB_PHY0, "usb-phy0", "osc24M", 0xcc, 8)
CCU_GATE(A31_CLK_USB_PHY1, "usb-phy1", "osc24M", 0xcc, 9)
CCU_GATE(A31_CLK_USB_PHY2, "usb-phy2", "osc24M", 0xcc, 10)
CCU_GATE(A31_CLK_USB_OHCI0, "usb-ohci0", "osc24M", 0xcc, 16)
CCU_GATE(A31_CLK_USB_OHCI1, "usb-ohci1", "osc24M", 0xcc, 17)
CCU_GATE(A31_CLK_USB_OHCI2, "usb-ohci2", "osc24M", 0xcc, 18)
CCU_GATE(A31_CLK_DRAM_VE, "dram-ve", "mdfs", 0x100, 0)
CCU_GATE(A31_CLK_DRAM_CSI_ISP, "dram-csi_isp", "mdfs", 0x100, 1)
CCU_GATE(A31_CLK_DRAM_TS, "dram-ts", "mdfs", 0x100, 3)
CCU_GATE(A31_CLK_DRAM_DRC0, "dram-drc0", "mdfs", 0x100, 16)
CCU_GATE(A31_CLK_DRAM_DRC1, "dram-drc1", "mdfs", 0x100, 17)
CCU_GATE(A31_CLK_DRAM_DEU0, "dram-deu0", "mdfs", 0x100, 18)
CCU_GATE(A31_CLK_DRAM_DEU1, "dram-deu1", "mdfs", 0x100, 19)
CCU_GATE(A31_CLK_DRAM_FE0, "dram-fe0", "mdfs", 0x100, 24)
CCU_GATE(A31_CLK_DRAM_FE1, "dram-fe1", "mdfs", 0x100, 25)
CCU_GATE(A31_CLK_DRAM_BE0, "dram-be0", "mdfs", 0x100, 26)
CCU_GATE(A31_CLK_DRAM_BE1, "dram-be1", "mdfs", 0x100, 27)
CCU_GATE(A31_CLK_DRAM_MP, "dram-mp", "mdfs", 0x100, 28)
CCU_GATE(A31_CLK_CODEC, "codec", "pll_audio", 0x140, 31)
CCU_GATE(A31_CLK_AVS, "avs", "pll_audio", 0x144, 31)
CCU_GATE(A31_CLK_DIGITAL_MIC, "digital-mic", "pll_audio", 0x148, 31)
CCU_GATE(A31_CLK_HDMI_DDC, "hdmi-ddc", "osc24M", 0x150, 30)
CCU_GATE(A31_CLK_PS, "ps", "lcd1_ch1", 0x154, 31)
};
static const char *pll_parents[] = {"osc24M"};
NKMP_CLK(pll_cpu_clk,
A31_CLK_PLL_CPU, /* id */
"pll_cpu", pll_parents, /* name, parents */
0x00, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 2, 0, 0, /* m factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK | AW_CLK_SCALE_CHANGE); /* flags */
NKMP_CLK(pll_audio_clk,
A31_CLK_PLL_AUDIO, /* id */
"pll_audio", pll_parents, /* name, parents */
0x08, /* offset */
8, 7, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
0, 4, 1, 0, /* m factor */
16, 3, 1, 0, /* p factor */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
static const char *pll_audio_mult_parents[] = {"pll_audio"};
FIXED_CLK(pll_audio_2x_clk,
A31_CLK_PLL_AUDIO_2X, /* id */
"pll_audio-2x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
FIXED_CLK(pll_audio_4x_clk,
A31_CLK_PLL_AUDIO_4X, /* id */
"pll_audio-4x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
4, /* mult */
1, /* div */
0); /* flags */
FIXED_CLK(pll_audio_8x_clk,
A31_CLK_PLL_AUDIO_8X, /* id */
"pll_audio-8x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
8, /* mult */
1, /* div */
0); /* flags */
NM_CLK_WITH_FRAC(pll_video0_clk,
A31_CLK_PLL_VIDEO0, /* id */
"pll_video0", pll_parents, /* name, parents */
0x10, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_video0_2x_parents[] = {"pll_video0"};
FIXED_CLK(pll_video0_2x_clk,
A31_CLK_PLL_VIDEO0_2X, /* id */
"pll_video0-2x", /* name */
pll_video0_2x_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
NM_CLK_WITH_FRAC(pll_ve_clk,
A31_CLK_PLL_VE, /* id */
"pll_ve", pll_parents, /* name, parents */
0x18, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
A31_CLK_PLL_DDR, /* id */
"pll_ddr", pll_parents, /* name, parents */
0x20, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 2, 0, 0, /* m factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
20, /* update */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
NKMP_CLK(pll_periph_clk,
A31_CLK_PLL_PERIPH, /* id */
"pll_periph", pll_parents, /* name, parents */
0x28, /* offset */
8, 4, 0, 0, /* n factor */
5, 2, 1, 0, /* k factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
static const char *pll_periph_2x_parents[] = {"pll_periph"};
FIXED_CLK(pll_periph_2x_clk,
A31_CLK_PLL_PERIPH_2X, /* id */
"pll_periph-2x", /* name */
pll_periph_2x_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
NM_CLK_WITH_FRAC(pll_video1_clk,
A31_CLK_PLL_VIDEO1, /* id */
"pll_video1", pll_parents, /* name, parents */
0x30, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_video1_2x_parents[] = {"pll_video1"};
FIXED_CLK(pll_video1_2x_clk,
A31_CLK_PLL_VIDEO1_2X, /* id */
"pll_video1-2x", /* name */
pll_video1_2x_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
NM_CLK_WITH_FRAC(pll_gpu_clk,
A31_CLK_PLL_GPU, /* id */
"pll_gpu", pll_parents, /* name, parents */
0x38, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_mipi_parents[] = {"pll_video0", "pll_video1"};
NKMP_CLK(pll_mipi_clk,
A31_CLK_PLL_MIPI, /* id */
"pll_mipi", pll_mipi_parents, /* name, parents */
0x40, /* offset */
8, 4, 0, 0, /* n factor */
4, 2, 1, 0, /* k factor */
0, 2, 0, 0, /* m factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
NM_CLK_WITH_FRAC(pll9_clk,
A31_CLK_PLL9, /* id */
"pll9", pll_parents, /* name, parents */
0x44, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
NM_CLK_WITH_FRAC(pll10_clk,
A31_CLK_PLL10, /* id */
"pll10", pll_parents, /* name, parents */
0x48, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static struct clk_div_table axi_div_table[] = {
{ .value = 0, .divider = 1, },
{ .value = 1, .divider = 2, },
{ .value = 2, .divider = 3, },
{ .value = 3, .divider = 4, },
{ .value = 4, .divider = 4, },
{ .value = 5, .divider = 4, },
{ .value = 6, .divider = 4, },
{ .value = 7, .divider = 4, },
{ },
};
static const char *axi_parents[] = {"cpu"};
DIV_CLK(axi_clk,
A31_CLK_AXI, /* id */
"axi", axi_parents, /* name, parents */
0x50, /* offset */
0, 2, /* shift, mask */
0, axi_div_table); /* flags, div table */
static const char *cpu_parents[] = {"osc32k", "osc24M", "pll_cpu", "pll_cpu"};
MUX_CLK(cpu_clk,
A31_CLK_CPU, /* id */
"cpu", cpu_parents, /* name, parents */
0x50, 16, 2); /* offset, shift, width */
static const char *ahb1_parents[] = {"osc32k", "osc24M", "axi", "pll_periph"};
PREDIV_CLK(ahb1_clk,
A31_CLK_AHB1, /* id */
"ahb1", ahb1_parents, /* name, parents */
0x54, /* offset */
12, 2, /* mux */
4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
12, 2, 3); /* prediv condition */
static const char *apb1_parents[] = {"ahb1"};
static struct clk_div_table apb1_div_table[] = {
{ .value = 0, .divider = 2, },
{ .value = 1, .divider = 2, },
{ .value = 2, .divider = 4, },
{ .value = 3, .divider = 8, },
{ },
};
DIV_CLK(apb1_clk,
A31_CLK_APB1, /* id */
"apb1", apb1_parents, /* name, parents */
0x54, /* offset */
8, 2, /* shift, mask */
CLK_DIV_WITH_TABLE, /* flags */
apb1_div_table); /* div table */
static const char *apb2_parents[] = {"osc32k", "osc24M", "pll_periph", "pll_periph"};
NM_CLK(apb2_clk,
A31_CLK_APB2, /* id */
"apb2", apb2_parents, /* name, parents */
0x58, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 5, 0, 0, /* m factor */
24, 2, /* mux */
0, /* gate */
AW_CLK_HAS_MUX);
static const char *mod_parents[] = {"osc24M", "pll_periph"};
NM_CLK(nand0_clk,
A31_CLK_NAND0, "nand0", mod_parents, /* id, name, parents */
0x80, /* offset */
16, 3, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(nand1_clk,
A31_CLK_NAND1, "nand1", mod_parents, /* id, name, parents */
0x80, /* offset */
16, 3, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(mmc0_clk,
A31_CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
0x88, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(mmc1_clk,
A31_CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
0x8c, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(mmc2_clk,
A31_CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
0x90, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(mmc3_clk,
A31_CLK_MMC2, "mmc3", mod_parents, /* id, name, parents */
0x94, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
static const char *ts_parents[] = {"osc24M", "pll_periph"};
NM_CLK(ts_clk,
A31_CLK_TS, "ts", ts_parents, /* id, name, parents */
0x98, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(ss_clk,
A31_CLK_SS, "ss", mod_parents, /* id, name, parents */
0x9C, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(spi0_clk,
A31_CLK_SPI0, "spi0", mod_parents, /* id, name, parents */
0xA0, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(spi1_clk,
A31_CLK_SPI1, "spi1", mod_parents, /* id, name, parents */
0xA4, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(spi2_clk,
A31_CLK_SPI2, "spi2", mod_parents, /* id, name, parents */
0xA8, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(spi3_clk,
A31_CLK_SPI3, "spi3", mod_parents, /* id, name, parents */
0xAC, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
static const char *daudio_parents[] = {"pll_audio-8x", "pll_audio-4x", "pll_audio-2x", "pll_audio"};
MUX_CLK(daudio0mux_clk,
0,
"daudio0mux", daudio_parents,
0xb0, 16, 2);
MUX_CLK(daudio1mux_clk,
0,
"daudio1mux", daudio_parents,
0xb4, 16, 2);
static const char *mdfs_parents[] = {"pll_ddr", "pll_periph"};
NM_CLK(mdfs_clk,
A31_CLK_MDFS, "mdfs", mdfs_parents, /* id, name, parents */
0xF0, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 4, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
static const char *dram_parents[] = {"pll_ddr", "pll_periph"};
NM_CLK(sdram0_clk,
A31_CLK_SDRAM0, "sdram0", dram_parents, /* id, name, parents */
0xF4, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
4, 1, /* mux */
0, /* gate */
AW_CLK_HAS_MUX); /* flags */
NM_CLK(sdram1_clk,
A31_CLK_SDRAM1, "sdram1", dram_parents, /* id, name, parents */
0xF4, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
8, 4, 0, 0, /* m factor */
12, 1, /* mux */
0, /* gate */
AW_CLK_HAS_MUX); /* flags */
static const char *befe_parents[] = {"pll_video0", "pll_video1", "pll_periph-2x", "pll_gpu", "pll9", "pll10"};
NM_CLK(be0_clk,
A31_CLK_BE0, "be0", befe_parents, /* id, name, parents */
0x104, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(be1_clk,
A31_CLK_BE1, "be1", befe_parents, /* id, name, parents */
0x108, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(fe0_clk,
A31_CLK_FE0, "fe0", befe_parents, /* id, name, parents */
0x104, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(fe1_clk,
A31_CLK_FE1, "fe1", befe_parents, /* id, name, parents */
0x108, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *mp_parents[] = {"pll_video0", "pll_video1", "pll9", "pll10"};
NM_CLK(mp_clk,
A31_CLK_MP, "mp", mp_parents, /* id, name, parents */
0x108, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *lcd_ch0_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x", "pll_mipi"};
NM_CLK(lcd0_ch0_clk,
A31_CLK_LCD0_CH0, "lcd0_ch0", lcd_ch0_parents, /* id, name, parents */
0x118, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake )*/
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(lcd1_ch0_clk,
A31_CLK_LCD1_CH0, "lcd1_ch0", lcd_ch0_parents, /* id, name, parents */
0x11C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake )*/
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *lcd_ch1_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x"};
NM_CLK(lcd0_ch1_clk,
A31_CLK_LCD0_CH1, "lcd0_ch1", lcd_ch1_parents, /* id, name, parents */
0x12C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(lcd1_ch1_clk,
A31_CLK_LCD1_CH1, "lcd1_ch1", lcd_ch1_parents, /* id, name, parents */
0x130, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 3, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
/* CSI0 0x134 Need Mux table */
/* CSI1 0x138 Need Mux table */
static const char *ve_parents[] = {"pll_ve"};
NM_CLK(ve_clk,
A31_CLK_VE, "ve", ve_parents, /* id, name, parents */
0x13C, /* offset */
16, 3, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
NM_CLK(hdmi_clk,
A31_CLK_HDMI, "hdmi", lcd_ch1_parents, /* id, name, parents */
0x150, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
static const char *mbus_parents[] = {"osc24M", "pll_periph", "pll_ddr"};
NM_CLK(mbus0_clk,
A31_CLK_MBUS0, "mbus0", mbus_parents, /* id, name, parents */
0x15C, /* offset */
16, 2, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(mbus1_clk,
A31_CLK_MBUS1, "mbus1", mbus_parents, /* id, name, parents */
0x160, /* offset */
16, 2, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *mipi_parents[] = {"pll_video0", "pll_video1", "pll_video0-2x", "pll_video1-2x"};
NM_CLK(mipi_dsi_clk,
A31_CLK_MIPI_DSI, "mipi_dsi", mipi_parents, /* id, name, parents */
0x168, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
16, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(mipi_dsi_dphy_clk,
A31_CLK_MIPI_DSI_DPHY, "mipi_dsi_dphy", mipi_parents, /* id, name, parents */
0x168, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
8, 2, /* mux */
15, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(mipi_csi_dphy_clk,
A31_CLK_MIPI_CSI_DPHY, "mipi_csi_dphy", mipi_parents, /* id, name, parents */
0x16C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
8, 2, /* mux */
15, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *iep_parents[] = {"pll_video0", "pll_video1", "pll_periph-2x", "pll_gpu", "pll9", "pll10"};
NM_CLK(iep_drc0_clk,
A31_CLK_IEP_DRC0, "iep_drc0", iep_parents, /* id, name, parents */
0x180, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(iep_drc1_clk,
A31_CLK_IEP_DRC1, "iep_drc1", iep_parents, /* id, name, parents */
0x184, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(iep_deu0_clk,
A31_CLK_IEP_DEU0, "iep_deu0", iep_parents, /* id, name, parents */
0x188, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
NM_CLK(iep_deu1_clk,
A31_CLK_IEP_DEU1, "iep_deu1", iep_parents, /* id, name, parents */
0x18C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *gpu_parents[] = {"pll_gpu", "pll_periph-2x", "pll_video0", "pll_video1", "pll9", "pll10"};
PREDIV_CLK(gpu_core_clk,
A31_CLK_GPU_CORE, /* id */
"gpu_core", gpu_parents, /* name, parents */
0x1A0, /* offset */
24, 3, /* mux */
0, 3, 0, 0, /* div */
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
24, 2, 1); /* prediv condition */
PREDIV_CLK(gpu_memory_clk,
A31_CLK_GPU_MEMORY, /* id */
"gpu_memory", gpu_parents, /* name, parents */
0x1A4, /* offset */
24, 3, /* mux */
0, 3, 0, 0, /* div */
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
24, 2, 1); /* prediv condition */
PREDIV_CLK(gpu_hyd_clk,
A31_CLK_GPU_HYD, /* id */
"gpu_hyd", gpu_parents, /* name, parents */
0x1A8, /* offset */
24, 3, /* mux */
0, 3, 0, 0, /* div */
0, 0, 3, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
24, 2, 1); /* prediv condition */
/* ATS 0x1B0 */
/* Trace 0x1B4 */
static struct aw_clk_nkmp_def *nkmp_clks[] = {
&pll_cpu_clk,
&pll_audio_clk,
&pll_periph_clk,
&pll_ddr_clk,
&pll_mipi_clk,
};
static struct aw_clk_nm_def *nm_clks[] = {
&pll_video0_clk,
&pll_ve_clk,
&pll_video1_clk,
&pll_gpu_clk,
&pll9_clk,
&pll10_clk,
&apb2_clk,
&nand0_clk,
&nand1_clk,
&mmc0_clk,
&mmc1_clk,
&mmc2_clk,
&mmc3_clk,
&ts_clk,
&ss_clk,
&spi0_clk,
&spi1_clk,
&spi2_clk,
&spi3_clk,
&mdfs_clk,
&sdram0_clk,
&sdram1_clk,
&be0_clk,
&be1_clk,
&fe0_clk,
&fe1_clk,
&mp_clk,
&lcd0_ch0_clk,
&lcd1_ch0_clk,
&lcd0_ch1_clk,
&lcd1_ch1_clk,
&ve_clk,
&hdmi_clk,
&mbus0_clk,
&mbus1_clk,
&mipi_dsi_clk,
&mipi_dsi_dphy_clk,
&mipi_csi_dphy_clk,
&iep_drc0_clk,
&iep_drc1_clk,
&iep_deu0_clk,
&iep_deu1_clk,
};
static struct aw_clk_prediv_mux_def *prediv_mux_clks[] = {
&ahb1_clk,
&gpu_core_clk,
&gpu_memory_clk,
&gpu_hyd_clk,
};
static struct clk_div_def *div_clks[] = {
&axi_clk,
&apb1_clk,
};
static struct clk_mux_def *mux_clks[] = {
&cpu_clk,
&daudio0mux_clk,
&daudio1mux_clk,
};
static struct clk_fixed_def *fixed_factor_clks[] = {
&pll_audio_2x_clk,
&pll_audio_4x_clk,
&pll_audio_8x_clk,
&pll_video0_2x_clk,
&pll_periph_2x_clk,
&pll_video1_2x_clk,
};
static struct aw_clk_init init_clks[] = {
};
void
ccu_a31_register_clocks(struct aw_ccung_softc *sc)
{
int i;
sc->resets = a31_ccu_resets;
sc->nresets = nitems(a31_ccu_resets);
sc->gates = a31_ccu_gates;
sc->ngates = nitems(a31_ccu_gates);
sc->clk_init = init_clks;
sc->n_clk_init = nitems(init_clks);
for (i = 0; i < nitems(nkmp_clks); i++)
aw_clk_nkmp_register(sc->clkdom, nkmp_clks[i]);
for (i = 0; i < nitems(nm_clks); i++)
aw_clk_nm_register(sc->clkdom, nm_clks[i]);
for (i = 0; i < nitems(prediv_mux_clks); i++)
aw_clk_prediv_mux_register(sc->clkdom, prediv_mux_clks[i]);
for (i = 0; i < nitems(mux_clks); i++)
clknode_mux_register(sc->clkdom, mux_clks[i]);
for (i = 0; i < nitems(div_clks); i++)
clknode_div_register(sc->clkdom, div_clks[i]);
for (i = 0; i < nitems(fixed_factor_clks); i++)
clknode_fixed_register(sc->clkdom, fixed_factor_clks[i]);
}

View File

@ -0,0 +1,250 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __CCU_A31_H__
#define __CCU_A31_H__
#define A31_RST_USB_PHY0 0
#define A31_RST_USB_PHY1 1
#define A31_RST_USB_PHY2 2
#define A31_RST_AHB1_MIPI_DSI 3
#define A31_RST_AHB1_SS 4
#define A31_RST_AHB1_DMA 5
#define A31_RST_AHB1_MMC0 6
#define A31_RST_AHB1_MMC1 7
#define A31_RST_AHB1_MMC2 8
#define A31_RST_AHB1_MMC3 9
#define A31_RST_AHB1_NAND1 10
#define A31_RST_AHB1_NAND0 11
#define A31_RST_AHB1_SDRAM 12
#define A31_RST_AHB1_EMAC 13
#define A31_RST_AHB1_TS 14
#define A31_RST_AHB1_HSTIMER 15
#define A31_RST_AHB1_SPI0 16
#define A31_RST_AHB1_SPI1 17
#define A31_RST_AHB1_SPI2 18
#define A31_RST_AHB1_SPI3 19
#define A31_RST_AHB1_OTG 20
#define A31_RST_AHB1_EHCI0 21
#define A31_RST_AHB1_EHCI1 22
#define A31_RST_AHB1_OHCI0 23
#define A31_RST_AHB1_OHCI1 24
#define A31_RST_AHB1_OHCI2 25
#define A31_RST_AHB1_VE 26
#define A31_RST_AHB1_LCD0 27
#define A31_RST_AHB1_LCD1 28
#define A31_RST_AHB1_CSI 29
#define A31_RST_AHB1_HDMI 30
#define A31_RST_AHB1_BE0 31
#define A31_RST_AHB1_BE1 32
#define A31_RST_AHB1_FE0 33
#define A31_RST_AHB1_FE1 34
#define A31_RST_AHB1_MP 35
#define A31_RST_AHB1_GPU 36
#define A31_RST_AHB1_DEU0 37
#define A31_RST_AHB1_DEU1 38
#define A31_RST_AHB1_DRC0 39
#define A31_RST_AHB1_DRC1 40
#define A31_RST_AHB1_LVDS 41
#define A31_RST_APB1_CODEC 42
#define A31_RST_APB1_SPDIF 43
#define A31_RST_APB1_DIGITAL_MIC 44
#define A31_RST_APB1_DAUDIO0 45
#define A31_RST_APB1_DAUDIO1 46
#define A31_RST_APB2_I2C0 47
#define A31_RST_APB2_I2C1 48
#define A31_RST_APB2_I2C2 49
#define A31_RST_APB2_I2C3 50
#define A31_RST_APB2_UART0 51
#define A31_RST_APB2_UART1 52
#define A31_RST_APB2_UART2 53
#define A31_RST_APB2_UART3 54
#define A31_RST_APB2_UART4 55
#define A31_RST_APB2_UART5 56
#define A31_CLK_PLL_CPU 0
#define A31_CLK_PLL_AUDIO_BASE 1
#define A31_CLK_PLL_AUDIO 2
#define A31_CLK_PLL_AUDIO_2X 3
#define A31_CLK_PLL_AUDIO_4X 4
#define A31_CLK_PLL_AUDIO_8X 5
#define A31_CLK_PLL_VIDEO0 6
#define A31_CLK_PLL_VIDEO0_2X 7
#define A31_CLK_PLL_VE 8
#define A31_CLK_PLL_DDR 9
#define A31_CLK_PLL_PERIPH 10
#define A31_CLK_PLL_PERIPH_2X 11
#define A31_CLK_PLL_VIDEO1 12
#define A31_CLK_PLL_VIDEO1_2X 13
#define A31_CLK_PLL_GPU 14
#define A31_CLK_PLL_MIPI 15
#define A31_CLK_PLL9 16
#define A31_CLK_PLL10 17
#define A31_CLK_CPU 18
#define A31_CLK_AXI 19
#define A31_CLK_AHB1 20
#define A31_CLK_APB1 21
#define A31_CLK_APB2 22
#define A31_CLK_AHB1_MIPIDSI 23
#define A31_CLK_AHB1_SS 24
#define A31_CLK_AHB1_DMA 25
#define A31_CLK_AHB1_MMC0 26
#define A31_CLK_AHB1_MMC1 27
#define A31_CLK_AHB1_MMC2 28
#define A31_CLK_AHB1_MMC3 29
#define A31_CLK_AHB1_NAND1 30
#define A31_CLK_AHB1_NAND0 31
#define A31_CLK_AHB1_SDRAM 32
#define A31_CLK_AHB1_EMAC 33
#define A31_CLK_AHB1_TS 34
#define A31_CLK_AHB1_HSTIMER 35
#define A31_CLK_AHB1_SPI0 36
#define A31_CLK_AHB1_SPI1 37
#define A31_CLK_AHB1_SPI2 38
#define A31_CLK_AHB1_SPI3 39
#define A31_CLK_AHB1_OTG 40
#define A31_CLK_AHB1_EHCI0 41
#define A31_CLK_AHB1_EHCI1 42
#define A31_CLK_AHB1_OHCI0 43
#define A31_CLK_AHB1_OHCI1 44
#define A31_CLK_AHB1_OHCI2 45
#define A31_CLK_AHB1_VE 46
#define A31_CLK_AHB1_LCD0 47
#define A31_CLK_AHB1_LCD1 48
#define A31_CLK_AHB1_CSI 49
#define A31_CLK_AHB1_HDMI 50
#define A31_CLK_AHB1_BE0 51
#define A31_CLK_AHB1_BE1 52
#define A31_CLK_AHB1_FE0 53
#define A31_CLK_AHB1_FE1 54
#define A31_CLK_AHB1_MP 55
#define A31_CLK_AHB1_GPU 56
#define A31_CLK_AHB1_DEU0 57
#define A31_CLK_AHB1_DEU1 58
#define A31_CLK_AHB1_DRC0 59
#define A31_CLK_AHB1_DRC1 60
#define A31_CLK_APB1_CODEC 61
#define A31_CLK_APB1_SPDIF 62
#define A31_CLK_APB1_DIGITAL_MIC 63
#define A31_CLK_APB1_PIO 64
#define A31_CLK_APB1_DAUDIO0 65
#define A31_CLK_APB1_DAUDIO1 66
#define A31_CLK_APB2_I2C0 67
#define A31_CLK_APB2_I2C1 68
#define A31_CLK_APB2_I2C2 69
#define A31_CLK_APB2_I2C3 70
#define A31_CLK_APB2_UART0 71
#define A31_CLK_APB2_UART1 72
#define A31_CLK_APB2_UART2 73
#define A31_CLK_APB2_UART3 74
#define A31_CLK_APB2_UART4 75
#define A31_CLK_APB2_UART5 76
#define A31_CLK_NAND0 77
#define A31_CLK_NAND1 78
#define A31_CLK_MMC0 79
#define A31_CLK_MMC0_SAMPLE 80
#define A31_CLK_MMC0_OUTPUT 81
#define A31_CLK_MMC1 82
#define A31_CLK_MMC1_SAMPLE 83
#define A31_CLK_MMC1_OUTPUT 84
#define A31_CLK_MMC2 85
#define A31_CLK_MMC2_SAMPLE 86
#define A31_CLK_MMC2_OUTPUT 87
#define A31_CLK_MMC3 88
#define A31_CLK_MMC3_SAMPLE 89
#define A31_CLK_MMC3_OUTPUT 90
#define A31_CLK_TS 91
#define A31_CLK_SS 92
#define A31_CLK_SPI0 93
#define A31_CLK_SPI1 94
#define A31_CLK_SPI2 95
#define A31_CLK_SPI3 96
#define A31_CLK_DAUDIO0 97
#define A31_CLK_DAUDIO1 98
#define A31_CLK_SPDIF 99
#define A31_CLK_USB_PHY0 100
#define A31_CLK_USB_PHY1 101
#define A31_CLK_USB_PHY2 102
#define A31_CLK_USB_OHCI0 103
#define A31_CLK_USB_OHCI1 104
#define A31_CLK_USB_OHCI2 105
#define A31_CLK_MDFS 107
#define A31_CLK_SDRAM0 108
#define A31_CLK_SDRAM1 109
#define A31_CLK_DRAM_VE 110
#define A31_CLK_DRAM_CSI_ISP 111
#define A31_CLK_DRAM_TS 112
#define A31_CLK_DRAM_DRC0 113
#define A31_CLK_DRAM_DRC1 114
#define A31_CLK_DRAM_DEU0 115
#define A31_CLK_DRAM_DEU1 116
#define A31_CLK_DRAM_FE0 117
#define A31_CLK_DRAM_FE1 118
#define A31_CLK_DRAM_BE0 119
#define A31_CLK_DRAM_BE1 120
#define A31_CLK_DRAM_MP 121
#define A31_CLK_BE0 122
#define A31_CLK_BE1 123
#define A31_CLK_FE0 124
#define A31_CLK_FE1 125
#define A31_CLK_MP 126
#define A31_CLK_LCD0_CH0 127
#define A31_CLK_LCD1_CH0 128
#define A31_CLK_LCD0_CH1 129
#define A31_CLK_LCD1_CH1 130
#define A31_CLK_CSI0_SCLK 131
#define A31_CLK_CSI0_MCLK 132
#define A31_CLK_CSI1_MCLK 133
#define A31_CLK_VE 134
#define A31_CLK_CODEC 135
#define A31_CLK_AVS 136
#define A31_CLK_DIGITAL_MIC 137
#define A31_CLK_HDMI 138
#define A31_CLK_HDMI_DDC 139
#define A31_CLK_PS 140
#define A31_CLK_MBUS0 141
#define A31_CLK_MBUS1 142
#define A31_CLK_MIPI_DSI 143
#define A31_CLK_MIPI_DSI_DPHY 144
#define A31_CLK_MIPI_CSI_DPHY 145
#define A31_CLK_IEP_DRC0 146
#define A31_CLK_IEP_DRC1 147
#define A31_CLK_IEP_DEU0 148
#define A31_CLK_IEP_DEU1 149
#define A31_CLK_GPU_CORE 150
#define A31_CLK_GPU_MEMORY 151
#define A31_CLK_GPU_HYD 152
#define A31_CLK_ATS 153
#define A31_CLK_TRACE 154
#define A31_CLK_OUT_A 155
#define A31_CLK_OUT_B 156
#define A31_CLK_OUT_C 157
void ccu_a31_register_clocks(struct aw_ccung_softc *sc);
#endif /* __CCU_A31 H__ */

View File

@ -0,0 +1,720 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
#include <sys/param.h>
#include <sys/systm.h>
#include <sys/bus.h>
#include <dev/extres/clk/clk_div.h>
#include <dev/extres/clk/clk_fixed.h>
#include <dev/extres/clk/clk_mux.h>
#include <arm/allwinner/clkng/aw_ccung.h>
#include <arm/allwinner/clkng/aw_clk.h>
#include <arm/allwinner/clkng/aw_clk_nm.h>
#include <arm/allwinner/clkng/aw_clk_nkmp.h>
#include <arm/allwinner/clkng/aw_clk_prediv_mux.h>
#include "ccu_h3.h"
static struct aw_ccung_reset h3_ccu_resets[] = {
CCU_RESET(H3_RST_USB_PHY0, 0xcc, 0)
CCU_RESET(H3_RST_USB_PHY1, 0xcc, 1)
CCU_RESET(H3_RST_USB_PHY2, 0xcc, 2)
CCU_RESET(H3_RST_USB_PHY3, 0xcc, 3)
CCU_RESET(H3_RST_MBUS, 0xfc, 31)
CCU_RESET(H3_RST_BUS_CE, 0x2c0, 5)
CCU_RESET(H3_RST_BUS_DMA, 0x2c0, 6)
CCU_RESET(H3_RST_BUS_MMC0, 0x2c0, 8)
CCU_RESET(H3_RST_BUS_MMC1, 0x2c0, 9)
CCU_RESET(H3_RST_BUS_MMC2, 0x2c0, 10)
CCU_RESET(H3_RST_BUS_NAND, 0x2c0, 13)
CCU_RESET(H3_RST_BUS_DRAM, 0x2c0, 14)
CCU_RESET(H3_RST_BUS_EMAC, 0x2c0, 17)
CCU_RESET(H3_RST_BUS_TS, 0x2c0, 18)
CCU_RESET(H3_RST_BUS_HSTIMER, 0x2c0, 19)
CCU_RESET(H3_RST_BUS_SPI0, 0x2c0, 20)
CCU_RESET(H3_RST_BUS_SPI1, 0x2c0, 21)
CCU_RESET(H3_RST_BUS_OTG, 0x2c0, 23)
CCU_RESET(H3_RST_BUS_EHCI0, 0x2c0, 24)
CCU_RESET(H3_RST_BUS_EHCI1, 0x2c0, 25)
CCU_RESET(H3_RST_BUS_EHCI2, 0x2c0, 26)
CCU_RESET(H3_RST_BUS_EHCI3, 0x2c0, 27)
CCU_RESET(H3_RST_BUS_OHCI0, 0x2c0, 28)
CCU_RESET(H3_RST_BUS_OHCI1, 0x2c0, 29)
CCU_RESET(H3_RST_BUS_OHCI2, 0x2c0, 30)
CCU_RESET(H3_RST_BUS_OHCI3, 0x2c0, 31)
CCU_RESET(H3_RST_BUS_VE, 0x2c4, 0)
CCU_RESET(H3_RST_BUS_TCON0, 0x2c4, 3)
CCU_RESET(H3_RST_BUS_TCON1, 0x2c4, 4)
CCU_RESET(H3_RST_BUS_DEINTERLACE, 0x2c4, 5)
CCU_RESET(H3_RST_BUS_CSI, 0x2c4, 8)
CCU_RESET(H3_RST_BUS_TVE, 0x2c4, 9)
CCU_RESET(H3_RST_BUS_HDMI0, 0x2c4, 10)
CCU_RESET(H3_RST_BUS_HDMI1, 0x2c4, 11)
CCU_RESET(H3_RST_BUS_DE, 0x2c4, 12)
CCU_RESET(H3_RST_BUS_GPU, 0x2c4, 20)
CCU_RESET(H3_RST_BUS_MSGBOX, 0x2c4, 21)
CCU_RESET(H3_RST_BUS_SPINLOCK, 0x2c4, 22)
CCU_RESET(H3_RST_BUS_DBG, 0x2c4, 31)
CCU_RESET(H3_RST_BUS_EPHY, 0x2c8, 2)
CCU_RESET(H3_RST_BUS_CODEC, 0x2d0, 0)
CCU_RESET(H3_RST_BUS_SPDIF, 0x2d0, 1)
CCU_RESET(H3_RST_BUS_THS, 0x2d0, 8)
CCU_RESET(H3_RST_BUS_I2S0, 0x2d0, 12)
CCU_RESET(H3_RST_BUS_I2S1, 0x2d0, 13)
CCU_RESET(H3_RST_BUS_I2S2, 0x2d0, 14)
CCU_RESET(H3_RST_BUS_I2C0, 0x2d8, 0)
CCU_RESET(H3_RST_BUS_I2C1, 0x2d8, 1)
CCU_RESET(H3_RST_BUS_I2C2, 0x2d8, 2)
CCU_RESET(H3_RST_BUS_UART0, 0x2d8, 16)
CCU_RESET(H3_RST_BUS_UART1, 0x2d8, 17)
CCU_RESET(H3_RST_BUS_UART2, 0x2d8, 18)
CCU_RESET(H3_RST_BUS_UART3, 0x2d8, 19)
CCU_RESET(H3_RST_BUS_SCR, 0x2d8, 20)
};
static struct aw_ccung_gate h3_ccu_gates[] = {
CCU_GATE(H3_CLK_BUS_CE, "bus-ce", "ahb1", 0x60, 5)
CCU_GATE(H3_CLK_BUS_DMA, "bus-dma", "ahb1", 0x60, 6)
CCU_GATE(H3_CLK_BUS_MMC0, "bus-mmc0", "ahb1", 0x60, 8)
CCU_GATE(H3_CLK_BUS_MMC1, "bus-mmc1", "ahb1", 0x60, 9)
CCU_GATE(H3_CLK_BUS_MMC2, "bus-mmc2", "ahb1", 0x60, 10)
CCU_GATE(H3_CLK_BUS_NAND, "bus-nand", "ahb1", 0x60, 13)
CCU_GATE(H3_CLK_BUS_DRAM, "bus-dram", "ahb1", 0x60, 14)
CCU_GATE(H3_CLK_BUS_EMAC, "bus-emac", "ahb2", 0x60, 17)
CCU_GATE(H3_CLK_BUS_TS, "bus-ts", "ahb1", 0x60, 18)
CCU_GATE(H3_CLK_BUS_HSTIMER, "bus-hstimer", "ahb1", 0x60, 19)
CCU_GATE(H3_CLK_BUS_SPI0, "bus-spi0", "ahb1", 0x60, 20)
CCU_GATE(H3_CLK_BUS_SPI1, "bus-spi1", "ahb1", 0x60, 21)
CCU_GATE(H3_CLK_BUS_OTG, "bus-otg", "ahb1", 0x60, 23)
CCU_GATE(H3_CLK_BUS_EHCI0, "bus-ehci0", "ahb1", 0x60, 24)
CCU_GATE(H3_CLK_BUS_EHCI1, "bus-ehci1", "ahb2", 0x60, 25)
CCU_GATE(H3_CLK_BUS_EHCI2, "bus-ehci2", "ahb2", 0x60, 26)
CCU_GATE(H3_CLK_BUS_EHCI3, "bus-ehci3", "ahb2", 0x60, 27)
CCU_GATE(H3_CLK_BUS_OHCI0, "bus-ohci0", "ahb1", 0x60, 28)
CCU_GATE(H3_CLK_BUS_OHCI1, "bus-ohci1", "ahb2", 0x60, 29)
CCU_GATE(H3_CLK_BUS_OHCI2, "bus-ohci2", "ahb2", 0x60, 30)
CCU_GATE(H3_CLK_BUS_OHCI3, "bus-ohci3", "ahb2", 0x60, 31)
CCU_GATE(H3_CLK_BUS_VE, "bus-ve", "ahb1", 0x64, 0)
CCU_GATE(H3_CLK_BUS_TCON0, "bus-tcon0", "ahb1", 0x64, 3)
CCU_GATE(H3_CLK_BUS_TCON1, "bus-tcon1", "ahb1", 0x64, 4)
CCU_GATE(H3_CLK_BUS_DEINTERLACE, "bus-deinterlace", "ahb1", 0x64, 5)
CCU_GATE(H3_CLK_BUS_CSI, "bus-csi", "ahb1", 0x64, 8)
CCU_GATE(H3_CLK_BUS_TVE, "bus-tve", "ahb1", 0x64, 9)
CCU_GATE(H3_CLK_BUS_HDMI, "bus-hdmi", "ahb1", 0x64, 11)
CCU_GATE(H3_CLK_BUS_DE, "bus-de", "ahb1", 0x64, 12)
CCU_GATE(H3_CLK_BUS_GPU, "bus-gpu", "ahb1", 0x64, 20)
CCU_GATE(H3_CLK_BUS_MSGBOX, "bus-msgbox", "ahb1", 0x64, 21)
CCU_GATE(H3_CLK_BUS_SPINLOCK, "bus-spinlock", "ahb1", 0x64, 22)
CCU_GATE(H3_CLK_BUS_CODEC, "bus-codec", "apb1", 0x68, 0)
CCU_GATE(H3_CLK_BUS_SPDIF, "bus-spdif", "apb1", 0x68, 1)
CCU_GATE(H3_CLK_BUS_PIO, "bus-pio", "apb1", 0x68, 5)
CCU_GATE(H3_CLK_BUS_THS, "bus-ths", "apb1", 0x68, 8)
CCU_GATE(H3_CLK_BUS_I2S0, "bus-i2s0", "apb1", 0x68, 12)
CCU_GATE(H3_CLK_BUS_I2S1, "bus-i2s1", "apb1", 0x68, 13)
CCU_GATE(H3_CLK_BUS_I2S2, "bus-i2s2", "apb1", 0x68, 14)
CCU_GATE(H3_CLK_BUS_I2C0, "bus-i2c0", "apb2", 0x6c, 0)
CCU_GATE(H3_CLK_BUS_I2C1, "bus-i2c1", "apb2", 0x6c, 1)
CCU_GATE(H3_CLK_BUS_I2C2, "bus-i2c2", "apb2", 0x6c, 2)
CCU_GATE(H3_CLK_BUS_UART0, "bus-uart0", "apb2", 0x6c, 16)
CCU_GATE(H3_CLK_BUS_UART1, "bus-uart1", "apb2", 0x6c, 17)
CCU_GATE(H3_CLK_BUS_UART2, "bus-uart2", "apb2", 0x6c, 18)
CCU_GATE(H3_CLK_BUS_UART3, "bus-uart3", "apb2", 0x6c, 19)
CCU_GATE(H3_CLK_BUS_SCR, "bus-scr", "apb2", 0x6c, 20)
CCU_GATE(H3_CLK_BUS_EPHY, "bus-ephy", "ahb1", 0x70, 0)
CCU_GATE(H3_CLK_BUS_DBG, "bus-dbg", "ahb1", 0x70, 7)
CCU_GATE(H3_CLK_USBPHY0, "usb-phy0", "osc24M", 0xcc, 8)
CCU_GATE(H3_CLK_USBPHY1, "usb-phy1", "osc24M", 0xcc, 9)
CCU_GATE(H3_CLK_USBPHY2, "usb-phy2", "osc24M", 0xcc, 10)
CCU_GATE(H3_CLK_USBPHY3, "usb-phy3", "osc24M", 0xcc, 11)
CCU_GATE(H3_CLK_USBOHCI0, "usb-ohci0", "osc24M", 0xcc, 16)
CCU_GATE(H3_CLK_USBOHCI1, "usb-ohci1", "osc24M", 0xcc, 17)
CCU_GATE(H3_CLK_USBOHCI2, "usb-ohci2", "osc24M", 0xcc, 18)
CCU_GATE(H3_CLK_USBOHCI3, "usb-ohci3", "osc24M", 0xcc, 19)
CCU_GATE(H3_CLK_THS, "ths", "thsdiv", 0x74, 31)
CCU_GATE(H3_CLK_I2S0, "i2s0", "i2s0mux", 0xB0, 31)
CCU_GATE(H3_CLK_I2S1, "i2s1", "i2s1mux", 0xB4, 31)
CCU_GATE(H3_CLK_I2S2, "i2s2", "i2s2mux", 0xB8, 31)
CCU_GATE(H3_CLK_DRAM_VE, "dram-ve", "dram", 0x100, 0)
CCU_GATE(H3_CLK_DRAM_CSI, "dram-csi", "dram", 0x100, 1)
CCU_GATE(H3_CLK_DRAM_DEINTERLACE, "dram-deinterlace", "dram", 0x100, 2)
CCU_GATE(H3_CLK_DRAM_TS, "dram-ts", "dram", 0x100, 3)
CCU_GATE(H3_CLK_AC_DIG, "ac-dig", "pll_audio", 0x140, 31)
CCU_GATE(H3_CLK_AVS, "avs", "osc24M", 0x144, 31)
CCU_GATE(H3_CLK_CSI_MISC, "csi-misc", "osc24M", 0x130, 31)
CCU_GATE(H3_CLK_HDMI_DDC, "hdmi-ddc", "osc24M", 0x154, 31)
};
static const char *pll_cpux_parents[] = {"osc24M"};
NKMP_CLK(pll_cpux_clk,
H3_CLK_PLL_CPUX, /* id */
"pll_cpux", pll_cpux_parents, /* name, parents */
0x00, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 2, 0, 0, /* m factor */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* p factor */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK | AW_CLK_SCALE_CHANGE); /* flags */
static const char *pll_audio_parents[] = {"osc24M"};
NKMP_CLK(pll_audio_clk,
H3_CLK_PLL_AUDIO, /* id */
"pll_audio", pll_audio_parents, /* name, parents */
0x08, /* offset */
8, 7, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* k factor (fake) */
0, 5, 0, 0, /* m factor */
16, 4, 0, 0, /* p factor */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
static const char *pll_audio_mult_parents[] = {"pll_audio"};
FIXED_CLK(pll_audio_2x_clk,
H3_CLK_PLL_AUDIO_2X, /* id */
"pll_audio-2x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
FIXED_CLK(pll_audio_4x_clk,
H3_CLK_PLL_AUDIO_4X, /* id */
"pll_audio-4x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
4, /* mult */
1, /* div */
0); /* flags */
FIXED_CLK(pll_audio_8x_clk,
H3_CLK_PLL_AUDIO_8X, /* id */
"pll_audio-8x", /* name */
pll_audio_mult_parents, /* parent */
0, /* freq */
8, /* mult */
1, /* div */
0); /* flags */
static const char *pll_video_parents[] = {"osc24M"};
NM_CLK_WITH_FRAC(pll_video_clk,
H3_CLK_PLL_VIDEO, /* id */
"pll_video", pll_video_parents, /* name, parents */
0x10, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_ve_parents[] = {"osc24M"};
NM_CLK_WITH_FRAC(pll_ve_clk,
H3_CLK_PLL_VE, /* id */
"pll_ve", pll_ve_parents, /* name, parents */
0x18, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_ddr_parents[] = {"osc24M"};
NKMP_CLK_WITH_UPDATE(pll_ddr_clk,
H3_CLK_PLL_DDR, /* id */
"pll_ddr", pll_ddr_parents, /* name, parents */
0x20, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 2, 0, 0, /* m factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
20, /* update */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
static const char *pll_periph0_parents[] = {"osc24M"};
static const char *pll_periph0_2x_parents[] = {"pll_periph0"};
NKMP_CLK(pll_periph0_clk,
H3_CLK_PLL_PERIPH0, /* id */
"pll_periph0", pll_periph0_parents, /* name, parents */
0x28, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
FIXED_CLK(pll_periph0_2x_clk,
H3_CLK_PLL_PERIPH0_2X, /* id */
"pll_periph0-2x", /* name */
pll_periph0_2x_parents, /* parent */
0, /* freq */
2, /* mult */
1, /* div */
0); /* flags */
static const char *pll_gpu_parents[] = {"osc24M"};
NM_CLK_WITH_FRAC(pll_gpu_clk,
H3_CLK_PLL_GPU, /* id */
"pll_gpu", pll_gpu_parents, /* name, parents */
0x38, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *pll_periph1_parents[] = {"osc24M"};
NKMP_CLK(pll_periph1_clk,
H3_CLK_PLL_PERIPH1, /* id */
"pll_periph1", pll_periph1_parents, /* name, parents */
0x44, /* offset */
8, 5, 0, 0, /* n factor */
4, 2, 0, 0, /* k factor */
0, 0, 2, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* p factor (fake) */
31, /* gate */
28, 1000, /* lock */
AW_CLK_HAS_GATE | AW_CLK_HAS_LOCK); /* flags */
static const char *pll_de_parents[] = {"osc24M"};
NM_CLK_WITH_FRAC(pll_de_clk,
H3_CLK_PLL_DE, /* id */
"pll_de", pll_de_parents, /* name, parents */
0x48, /* offset */
8, 7, 0, 0, /* n factor */
0, 4, 0, 0, /* m factor */
31, 28, 1000, /* gate, lock, lock retries */
AW_CLK_HAS_LOCK, /* flags */
270000000, 297000000, /* freq0, freq1 */
24, 25); /* mode sel, freq sel */
static const char *cpux_parents[] = {"osc32k", "osc24M", "pll_cpux", "pll_cpux"};
MUX_CLK(cpux_clk,
H3_CLK_CPUX, /* id */
"cpux", cpux_parents, /* name, parents */
0x50, 16, 2); /* offset, shift, width */
static const char *axi_parents[] = {"cpux"};
DIV_CLK(axi_clk,
H3_CLK_AXI, /* id */
"axi", axi_parents, /* name, parents */
0x50, /* offset */
0, 2, /* shift, width */
0, NULL); /* flags, div table */
static const char *ahb1_parents[] = {"osc32k", "osc24M", "axi", "pll_periph0"};
PREDIV_CLK(ahb1_clk, H3_CLK_AHB1, /* id */
"ahb1", ahb1_parents, /* name, parents */
0x54, /* offset */
12, 2, /* mux */
4, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* div */
6, 2, 0, AW_CLK_FACTOR_HAS_COND, /* prediv */
12, 2, 3); /* prediv condition */
static const char *apb1_parents[] = {"ahb1"};
static struct clk_div_table apb1_div_table[] = {
{ .value = 0, .divider = 2, },
{ .value = 1, .divider = 2, },
{ .value = 2, .divider = 4, },
{ .value = 3, .divider = 8, },
{ },
};
DIV_CLK(apb1_clk,
H3_CLK_APB1, /* id */
"apb1", apb1_parents, /* name, parents */
0x54, /* offset */
8, 2, /* shift, width */
CLK_DIV_WITH_TABLE, /* flags */
apb1_div_table); /* div table */
static const char *apb2_parents[] = {"osc32k", "osc24M", "pll_periph0", "pll_periph0"};
NM_CLK(apb2_clk,
H3_CLK_APB2, /* id */
"apb2", apb2_parents, /* name, parents */
0x58, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 5, 0, 0, /* m factor */
24, 2, /* mux */
0, /* gate */
AW_CLK_HAS_MUX);
static const char *ahb2_parents[] = {"ahb1", "pll_periph0"};
PREDIV_CLK(ahb2_clk, H3_CLK_AHB2, /* id */
"ahb2", ahb2_parents, /* name, parents */
0x5c, /* offset */
0, 2, /* mux */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* div */
0, 0, 2, AW_CLK_FACTOR_HAS_COND | AW_CLK_FACTOR_FIXED, /* prediv */
0, 2, 1); /* prediv condition */
static const char *ths_parents[] = {"osc24M"};
static struct clk_div_table ths_div_table[] = {
{ .value = 0, .divider = 1, },
{ .value = 1, .divider = 2, },
{ .value = 2, .divider = 4, },
{ .value = 3, .divider = 6, },
{ },
};
DIV_CLK(thsdiv_clk,
0, /* id */
"thsdiv", ths_parents, /* name, parents */
0x74, /* offset */
0, 2, /* shift, width */
CLK_DIV_WITH_TABLE, /* flags */
ths_div_table); /* div table */
static const char *mod_parents[] = {"osc24M", "pll_periph0", "pll_periph1"};
NM_CLK(nand_clk,
H3_CLK_NAND, "nand", mod_parents, /* id, name, parents */
0x80, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(mmc0_clk,
H3_CLK_MMC0, "mmc0", mod_parents, /* id, name, parents */
0x88, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(mmc1_clk,
H3_CLK_MMC1, "mmc1", mod_parents, /* id, name, parents */
0x8c, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(mmc2_clk,
H3_CLK_MMC2, "mmc2", mod_parents, /* id, name, parents */
0x90, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
static const char *ts_parents[] = {"osc24M", "pll_periph0"};
NM_CLK(ts_clk,
H3_CLK_TS, "ts", ts_parents, /* id, name, parents */
0x98, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(ce_clk,
H3_CLK_CE, "ce", mod_parents, /* id, name, parents */
0x9C, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX); /* flags */
NM_CLK(spi0_clk,
H3_CLK_SPI0, "spi0", mod_parents, /* id, name, parents */
0xA0, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
NM_CLK(spi1_clk,
H3_CLK_SPI1, "spi1", mod_parents, /* id, name, parents */
0xA4, /* offset */
16, 2, 0, AW_CLK_FACTOR_POWER_OF_TWO, /* n factor */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_GATE | AW_CLK_HAS_MUX |
AW_CLK_REPARENT); /* flags */
static const char *i2s_parents[] = {"pll_audio-8x", "pll_audio-4x", "pll_audio-2x", "pll_audio"};
MUX_CLK(i2s0mux_clk,
0, "i2s0mux", i2s_parents, /* id, name, parents */
0xb0, 16, 2); /* offset, mux shift, mux width */
MUX_CLK(i2s1mux_clk,
0, "i2s1mux", i2s_parents, /* id, name, parents */
0xb4, 16, 2); /* offset, mux shift, mux width */
MUX_CLK(i2s2mux_clk,
0, "i2s2mux", i2s_parents, /* id, name, parents */
0xb8, 16, 2); /* offset, mux shift, mux width */
static const char *spdif_parents[] = {"pll_audio"};
NM_CLK(spdif_clk,
H3_CLK_SPDIF, "spdif", spdif_parents, /* id, name, parents */
0xC0, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake); */
0, 4, 0, 0, /* m factor */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
static const char *dram_parents[] = {"pll_ddr", "pll_periph0-2x"};
NM_CLK(dram_clk,
H3_CLK_DRAM, "dram", dram_parents, /* id, name, parents */
0xF4, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
20, 2, /* mux */
0, /* gate */
AW_CLK_HAS_MUX); /* flags */
static const char *de_parents[] = {"pll_periph0-2x", "pll_de"};
NM_CLK(de_clk,
H3_CLK_DE, "de", de_parents, /* id, name, parents */
0x104, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *tcon0_parents[] = {"pll_video"};
NM_CLK(tcon0_clk,
H3_CLK_TCON0, "tcon0", tcon0_parents, /* id, name, parents */
0x118, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *tve_parents[] = {"pll_de", "pll_periph1"};
NM_CLK(tve_clk,
H3_CLK_TVE, "tve", tve_parents, /* id, name, parents */
0x120, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *deinterlace_parents[] = {"pll_periph0", "pll_periph1"};
NM_CLK(deinterlace_clk,
H3_CLK_DEINTERLACE, "deinterlace", deinterlace_parents, /* id, name, parents */
0x124, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *csi_sclk_parents[] = {"pll_periph0", "pll_periph1"};
NM_CLK(csi_sclk_clk,
H3_CLK_CSI_SCLK, "csi-sclk", csi_sclk_parents, /* id, name, parents */
0x134, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
16, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *csi_mclk_parents[] = {"osc24M", "pll_video", "pll_periph1"};
NM_CLK(csi_mclk_clk,
H3_CLK_CSI_MCLK, "csi-mclk", csi_mclk_parents, /* id, name, parents */
0x134, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
8, 2, /* mux */
15, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *ve_parents[] = {"pll_ve"};
NM_CLK(ve_clk,
H3_CLK_VE, "ve", ve_parents, /* id, name, parents */
0x13C, /* offset */
16, 3, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
static const char *hdmi_parents[] = {"pll_video"};
NM_CLK(hdmi_clk,
H3_CLK_HDMI, "hdmi", hdmi_parents, /* id, name, parents */
0x150, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 4, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *mbus_parents[] = {"osc24M", "pll_periph0-2x", "pll_ddr"};
NM_CLK(mbus_clk,
H3_CLK_MBUS, "mbus", mbus_parents, /* id, name, parents */
0x15C, /* offset */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* n factor (fake) */
0, 3, 0, 0, /* m factor */
24, 2, /* mux */
31, /* gate */
AW_CLK_HAS_MUX | AW_CLK_HAS_GATE); /* flags */
static const char *gpu_parents[] = {"pll_gpu"};
NM_CLK(gpu_clk,
H3_CLK_GPU, "gpu", gpu_parents, /* id, name, parents */
0x1A0, /* offset */
0, 2, 0, 0, /* n factor */
0, 0, 1, AW_CLK_FACTOR_FIXED, /* m factor (fake) */
0, 0, /* mux */
31, /* gate */
AW_CLK_HAS_GATE); /* flags */
static struct aw_clk_nkmp_def *nkmp_clks[] = {
&pll_cpux_clk,
&pll_audio_clk,
&pll_periph0_clk,
&pll_periph1_clk,
&pll_ddr_clk,
};
static struct aw_clk_nm_def *nm_clks[] = {
&pll_video_clk,
&pll_ve_clk,
&pll_gpu_clk,
&pll_de_clk,
&apb2_clk,
&nand_clk,
&mmc0_clk,
&mmc1_clk,
&mmc2_clk,
&ts_clk,
&ce_clk,
&spi0_clk,
&spi1_clk,
&spdif_clk,
&dram_clk,
&de_clk,
&tcon0_clk,
&tve_clk,
&deinterlace_clk,
&csi_sclk_clk,
&csi_mclk_clk,
&ve_clk,
&hdmi_clk,
&mbus_clk,
&gpu_clk,
};
static struct aw_clk_prediv_mux_def *prediv_mux_clks[] = {
&ahb1_clk,
&ahb2_clk,
};
static struct clk_mux_def *mux_clks[] = {
&cpux_clk,
&i2s0mux_clk,
&i2s1mux_clk,
&i2s2mux_clk,
};
static struct clk_div_def *div_clks[] = {
&axi_clk,
&apb1_clk,
&thsdiv_clk,
};
static struct clk_fixed_def *fixed_factor_clks[] = {
&pll_periph0_2x_clk,
&pll_audio_2x_clk,
&pll_audio_4x_clk,
&pll_audio_8x_clk,
};
static struct aw_clk_init init_clks[] = {
{"ahb1", "pll_periph0", 0, false},
{"ahb2", "pll_periph0", 0, false},
{"dram", "pll_ddr", 0, false},
};
void
ccu_h3_register_clocks(struct aw_ccung_softc *sc)
{
int i;
sc->resets = h3_ccu_resets;
sc->nresets = nitems(h3_ccu_resets);
sc->gates = h3_ccu_gates;
sc->ngates = nitems(h3_ccu_gates);
sc->clk_init = init_clks;
sc->n_clk_init = nitems(init_clks);
for (i = 0; i < nitems(nkmp_clks); i++)
aw_clk_nkmp_register(sc->clkdom, nkmp_clks[i]);
for (i = 0; i < nitems(nm_clks); i++)
aw_clk_nm_register(sc->clkdom, nm_clks[i]);
for (i = 0; i < nitems(prediv_mux_clks); i++)
aw_clk_prediv_mux_register(sc->clkdom, prediv_mux_clks[i]);
for (i = 0; i < nitems(mux_clks); i++)
clknode_mux_register(sc->clkdom, mux_clks[i]);
for (i = 0; i < nitems(div_clks); i++)
clknode_div_register(sc->clkdom, div_clks[i]);
for (i = 0; i < nitems(fixed_factor_clks); i++)
clknode_fixed_register(sc->clkdom, fixed_factor_clks[i]);
}

View File

@ -0,0 +1,205 @@
/*-
* Copyright (c) 2017 Emmanuel Vadot <manu@freebsd.org>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``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 BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
* AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef __CCU_H3_H__
#define __CCU_H3_H__
#define H3_RST_USB_PHY0 0
#define H3_RST_USB_PHY1 1
#define H3_RST_USB_PHY2 2
#define H3_RST_USB_PHY3 3
#define H3_RST_MBUS 4
#define H3_RST_BUS_CE 5
#define H3_RST_BUS_DMA 6
#define H3_RST_BUS_MMC0 7
#define H3_RST_BUS_MMC1 8
#define H3_RST_BUS_MMC2 9
#define H3_RST_BUS_NAND 10
#define H3_RST_BUS_DRAM 11
#define H3_RST_BUS_EMAC 12
#define H3_RST_BUS_TS 13
#define H3_RST_BUS_HSTIMER 14
#define H3_RST_BUS_SPI0 15
#define H3_RST_BUS_SPI1 16
#define H3_RST_BUS_OTG 17
#define H3_RST_BUS_EHCI0 18
#define H3_RST_BUS_EHCI1 19
#define H3_RST_BUS_EHCI2 20
#define H3_RST_BUS_EHCI3 21
#define H3_RST_BUS_OHCI0 22
#define H3_RST_BUS_OHCI1 23
#define H3_RST_BUS_OHCI2 24
#define H3_RST_BUS_OHCI3 25
#define H3_RST_BUS_VE 26
#define H3_RST_BUS_TCON0 27
#define H3_RST_BUS_TCON1 28
#define H3_RST_BUS_DEINTERLACE 29
#define H3_RST_BUS_CSI 30
#define H3_RST_BUS_TVE 31
#define H3_RST_BUS_HDMI0 32
#define H3_RST_BUS_HDMI1 33
#define H3_RST_BUS_DE 34
#define H3_RST_BUS_GPU 35
#define H3_RST_BUS_MSGBOX 36
#define H3_RST_BUS_SPINLOCK 37
#define H3_RST_BUS_DBG 38
#define H3_RST_BUS_EPHY 39
#define H3_RST_BUS_CODEC 40
#define H3_RST_BUS_SPDIF 41
#define H3_RST_BUS_THS 42
#define H3_RST_BUS_I2S0 43
#define H3_RST_BUS_I2S1 44
#define H3_RST_BUS_I2S2 45
#define H3_RST_BUS_I2C0 46
#define H3_RST_BUS_I2C1 47
#define H3_RST_BUS_I2C2 48
#define H3_RST_BUS_UART0 49
#define H3_RST_BUS_UART1 50
#define H3_RST_BUS_UART2 51
#define H3_RST_BUS_UART3 52
#define H3_RST_BUS_SCR 53
#define H3_CLK_PLL_CPUX 0
#define H3_CLK_PLL_AUDIO_BASE 1
#define H3_CLK_PLL_AUDIO 2
#define H3_CLK_PLL_AUDIO_2X 3
#define H3_CLK_PLL_AUDIO_4X 4
#define H3_CLK_PLL_AUDIO_8X 5
#define H3_CLK_PLL_VIDEO 6
#define H3_CLK_PLL_VE 7
#define H3_CLK_PLL_DDR 8
#define H3_CLK_PLL_PERIPH0 9
#define H3_CLK_PLL_PERIPH0_2X 10
#define H3_CLK_PLL_GPU 11
#define H3_CLK_PLL_PERIPH1 12
#define H3_CLK_PLL_DE 13
#define H3_CLK_CPUX 14
#define H3_CLK_AXI 15
#define H3_CLK_AHB1 16
#define H3_CLK_APB1 17
#define H3_CLK_APB2 18
#define H3_CLK_AHB2 19
#define H3_CLK_BUS_CE 20
#define H3_CLK_BUS_DMA 21
#define H3_CLK_BUS_MMC0 22
#define H3_CLK_BUS_MMC1 23
#define H3_CLK_BUS_MMC2 24
#define H3_CLK_BUS_NAND 25
#define H3_CLK_BUS_DRAM 26
#define H3_CLK_BUS_EMAC 27
#define H3_CLK_BUS_TS 28
#define H3_CLK_BUS_HSTIMER 29
#define H3_CLK_BUS_SPI0 30
#define H3_CLK_BUS_SPI1 31
#define H3_CLK_BUS_OTG 32
#define H3_CLK_BUS_EHCI0 33
#define H3_CLK_BUS_EHCI1 34
#define H3_CLK_BUS_EHCI2 35
#define H3_CLK_BUS_EHCI3 36
#define H3_CLK_BUS_OHCI0 37
#define H3_CLK_BUS_OHCI1 38
#define H3_CLK_BUS_OHCI2 39
#define H3_CLK_BUS_OHCI3 40
#define H3_CLK_BUS_VE 41
#define H3_CLK_BUS_TCON0 42
#define H3_CLK_BUS_TCON1 43
#define H3_CLK_BUS_DEINTERLACE 44
#define H3_CLK_BUS_CSI 45
#define H3_CLK_BUS_TVE 46
#define H3_CLK_BUS_HDMI 47
#define H3_CLK_BUS_DE 48
#define H3_CLK_BUS_GPU 49
#define H3_CLK_BUS_MSGBOX 50
#define H3_CLK_BUS_SPINLOCK 51
#define H3_CLK_BUS_CODEC 52
#define H3_CLK_BUS_SPDIF 53
#define H3_CLK_BUS_PIO 54
#define H3_CLK_BUS_THS 55
#define H3_CLK_BUS_I2S0 56
#define H3_CLK_BUS_I2S1 57
#define H3_CLK_BUS_I2S2 58
#define H3_CLK_BUS_I2C0 59
#define H3_CLK_BUS_I2C1 60
#define H3_CLK_BUS_I2C2 61
#define H3_CLK_BUS_UART0 62
#define H3_CLK_BUS_UART1 63
#define H3_CLK_BUS_UART2 64
#define H3_CLK_BUS_UART3 65
#define H3_CLK_BUS_SCR 66
#define H3_CLK_BUS_EPHY 67
#define H3_CLK_BUS_DBG 68
#define H3_CLK_THS 69
#define H3_CLK_NAND 70
#define H3_CLK_MMC0 71
#define H3_CLK_MMC0_SAMPLE 72
#define H3_CLK_MMC0_OUTPUT 73
#define H3_CLK_MMC1 74
#define H3_CLK_MMC1_SAMPLE 75
#define H3_CLK_MMC1_OUTPUT 76
#define H3_CLK_MMC2 77
#define H3_CLK_MMC2_SAMPLE 78
#define H3_CLK_MMC2_OUTPUT 79
#define H3_CLK_TS 80
#define H3_CLK_CE 81
#define H3_CLK_SPI0 82
#define H3_CLK_SPI1 83
#define H3_CLK_I2S0 84
#define H3_CLK_I2S1 85
#define H3_CLK_I2S2 86
#define H3_CLK_SPDIF 87
#define H3_CLK_USBPHY0 88
#define H3_CLK_USBPHY1 89
#define H3_CLK_USBPHY2 90
#define H3_CLK_USBPHY3 91
#define H3_CLK_USBOHCI0 92
#define H3_CLK_USBOHCI1 93
#define H3_CLK_USBOHCI2 94
#define H3_CLK_USBOHCI3 95
#define H3_CLK_DRAM 96
#define H3_CLK_DRAM_VE 97
#define H3_CLK_DRAM_CSI 98
#define H3_CLK_DRAM_DEINTERLACE 99
#define H3_CLK_DRAM_TS 100
#define H3_CLK_DE 101
#define H3_CLK_TCON0 102
#define H3_CLK_TVE 103
#define H3_CLK_DEINTERLACE 104
#define H3_CLK_CSI_MISC 105
#define H3_CLK_CSI_SCLK 106
#define H3_CLK_CSI_MCLK 107
#define H3_CLK_VE 108
#define H3_CLK_AC_DIG 109
#define H3_CLK_AVS 110
#define H3_CLK_HDMI 111
#define H3_CLK_HDMI_DDC 112
#define H3_CLK_MBUS 113
#define H3_CLK_GPU 114
void ccu_h3_register_clocks(struct aw_ccung_softc *sc);
#endif /* __CCU_H3_H__ */

View File

@ -56,3 +56,8 @@ arm/allwinner/clk/aw_oscclk.c standard
arm/allwinner/clk/aw_pll.c standard
arm/allwinner/clk/aw_thsclk.c standard
arm/allwinner/clk/aw_usbclk.c standard
arm/allwinner/clkng/aw_ccung.c standard
arm/allwinner/clkng/aw_clk_nkmp.c standard
arm/allwinner/clkng/aw_clk_nm.c standard
arm/allwinner/clkng/aw_clk_prediv_mux.c standard

View File

@ -1,4 +1,5 @@
# $FreeBSD$
arm/allwinner/clkng/ccu_h3.c standard
arm/allwinner/h3/h3_padconf.c standard
arm/allwinner/h3/h3_r_padconf.c standard

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@ -54,6 +54,7 @@ __FBSDID("$FreeBSD$");
#include "platform_if.h"
#if defined(SOC_ALTERA_CYCLONE5)
static int
socfpga_devmap_init(platform_t plat)
{
@ -82,25 +83,47 @@ socfpga_devmap_init(platform_t plat)
return (0);
}
#endif
#if defined(SOC_ALTERA_ARRIA10)
static int
socfpga_a10_devmap_init(platform_t plat)
{
/* UART */
devmap_add_entry(0xffc00000, 0x100000);
/* USB OTG */
devmap_add_entry(0xffb00000, 0x100000);
/* dwmmc */
devmap_add_entry(0xff800000, 0x100000);
/* scu */
devmap_add_entry(0xfff00000, 0x100000);
return (0);
}
#endif
static void
socfpga_cpu_reset(platform_t plat)
_socfpga_cpu_reset(bus_size_t reg)
{
uint32_t paddr;
bus_addr_t vaddr;
phandle_t node;
if (rstmgr_warmreset() == 0)
if (rstmgr_warmreset(reg) == 0)
goto end;
node = OF_finddevice("rstmgr");
node = OF_finddevice("/soc/rstmgr");
if (node == -1)
goto end;
if ((OF_getencprop(node, "reg", &paddr, sizeof(paddr))) > 0) {
if (bus_space_map(fdtbus_bs_tag, paddr, 0x8, 0, &vaddr) == 0) {
bus_space_write_4(fdtbus_bs_tag, vaddr,
RSTMGR_CTRL, CTRL_SWWARMRSTREQ);
reg, CTRL_SWWARMRSTREQ);
}
}
@ -108,16 +131,46 @@ socfpga_cpu_reset(platform_t plat)
while (1);
}
#if defined(SOC_ALTERA_CYCLONE5)
static void
socfpga_cpu_reset(platform_t plat)
{
_socfpga_cpu_reset(RSTMGR_CTRL);
}
#endif
#if defined(SOC_ALTERA_ARRIA10)
static void
socfpga_a10_cpu_reset(platform_t plat)
{
_socfpga_cpu_reset(RSTMGR_A10_CTRL);
}
#endif
#if defined(SOC_ALTERA_CYCLONE5)
static platform_method_t socfpga_methods[] = {
PLATFORMMETHOD(platform_devmap_init, socfpga_devmap_init),
PLATFORMMETHOD(platform_cpu_reset, socfpga_cpu_reset),
#ifdef SMP
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
PLATFORMMETHOD(platform_mp_start_ap, socfpga_mp_start_ap),
#endif
PLATFORMMETHOD_END,
};
FDT_PLATFORM_DEF(socfpga, "socfpga", 0, "altr,socfpga-cyclone5", 200);
#endif
FDT_PLATFORM_DEF(socfpga, "socfpga", 0, "altr,socfpga", 0);
#if defined(SOC_ALTERA_ARRIA10)
static platform_method_t socfpga_a10_methods[] = {
PLATFORMMETHOD(platform_devmap_init, socfpga_a10_devmap_init),
PLATFORMMETHOD(platform_cpu_reset, socfpga_a10_cpu_reset),
#ifdef SMP
PLATFORMMETHOD(platform_mp_setmaxid, socfpga_mp_setmaxid),
PLATFORMMETHOD(platform_mp_start_ap, socfpga_a10_mp_start_ap),
#endif
PLATFORMMETHOD_END,
};
FDT_PLATFORM_DEF(socfpga_a10, "socfpga", 0, "altr,socfpga-arria10", 200);
#endif

View File

@ -377,7 +377,7 @@ fpgamgr_probe(device_t dev)
if (!ofw_bus_status_okay(dev))
return (ENXIO);
if (!ofw_bus_is_compatible(dev, "altr,fpga-mgr"))
if (!ofw_bus_is_compatible(dev, "altr,socfpga-fpga-mgr"))
return (ENXIO);
device_set_desc(dev, "FPGA Manager");

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@ -50,8 +50,10 @@ __FBSDID("$FreeBSD$");
#include <machine/platformvar.h>
#include <arm/altera/socfpga/socfpga_mp.h>
#include <arm/altera/socfpga/socfpga_rstmgr.h>
#define SCU_PHYSBASE 0xFFFEC000
#define SCU_PHYSBASE_A10 0xFFFFC000
#define SCU_SIZE 0x100
#define SCU_CONTROL_REG 0x00
@ -69,11 +71,12 @@ __FBSDID("$FreeBSD$");
#define RSTMGR_PHYSBASE 0xFFD05000
#define RSTMGR_SIZE 0x100
#define MPUMODRST 0x10
#define MPUMODRST_CPU1 (1 << 1)
#define RAM_PHYSBASE 0x0
#define RAM_SIZE 0x1000
#define RAM_SIZE 0x1000
#define SOCFPGA_ARRIA10 1
#define SOCFPGA_CYCLONE5 2
extern char *mpentry_addr;
static void socfpga_trampoline(void);
@ -109,15 +112,31 @@ socfpga_mp_setmaxid(platform_t plat)
mp_maxid = ncpu - 1;
}
void
socfpga_mp_start_ap(platform_t plat)
static void
_socfpga_mp_start_ap(uint32_t platid)
{
bus_space_handle_t scu, rst, ram;
int reg;
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE,
SCU_SIZE, 0, &scu) != 0)
panic("Couldn't map the SCU\n");
switch (platid) {
#if defined(SOC_ALTERA_ARRIA10)
case SOCFPGA_ARRIA10:
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE_A10,
SCU_SIZE, 0, &scu) != 0)
panic("Couldn't map the SCU\n");
break;
#endif
#if defined(SOC_ALTERA_CYCLONE5)
case SOCFPGA_CYCLONE5:
if (bus_space_map(fdtbus_bs_tag, SCU_PHYSBASE,
SCU_SIZE, 0, &scu) != 0)
panic("Couldn't map the SCU\n");
break;
#endif
default:
panic("Unknown platform id %d\n", platid);
}
if (bus_space_map(fdtbus_bs_tag, RSTMGR_PHYSBASE,
RSTMGR_SIZE, 0, &rst) != 0)
panic("Couldn't map the reset manager (RSTMGR)\n");
@ -139,7 +158,22 @@ socfpga_mp_start_ap(platform_t plat)
bus_space_write_4(fdtbus_bs_tag, scu, SCU_DIAG_CONTROL, reg);
/* Put CPU1 to reset state */
bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, MPUMODRST_CPU1);
switch (platid) {
#if defined(SOC_ALTERA_ARRIA10)
case SOCFPGA_ARRIA10:
bus_space_write_4(fdtbus_bs_tag, rst,
RSTMGR_A10_MPUMODRST, MPUMODRST_CPU1);
break;
#endif
#if defined(SOC_ALTERA_CYCLONE5)
case SOCFPGA_CYCLONE5:
bus_space_write_4(fdtbus_bs_tag, rst,
RSTMGR_MPUMODRST, MPUMODRST_CPU1);
break;
#endif
default:
panic("Unknown platform id %d\n", platid);
}
/* Enable the SCU, then clean the cache on this core */
reg = bus_space_read_4(fdtbus_bs_tag, scu, SCU_CONTROL_REG);
@ -154,7 +188,22 @@ socfpga_mp_start_ap(platform_t plat)
dcache_wbinv_poc_all();
/* Put CPU1 out from reset */
bus_space_write_4(fdtbus_bs_tag, rst, MPUMODRST, 0);
switch (platid) {
#if defined(SOC_ALTERA_ARRIA10)
case SOCFPGA_ARRIA10:
bus_space_write_4(fdtbus_bs_tag, rst,
RSTMGR_A10_MPUMODRST, 0);
break;
#endif
#if defined(SOC_ALTERA_CYCLONE5)
case SOCFPGA_CYCLONE5:
bus_space_write_4(fdtbus_bs_tag, rst,
RSTMGR_MPUMODRST, 0);
break;
#endif
default:
panic("Unknown platform id %d\n", platid);
}
dsb();
sev();
@ -163,3 +212,21 @@ socfpga_mp_start_ap(platform_t plat)
bus_space_unmap(fdtbus_bs_tag, rst, RSTMGR_SIZE);
bus_space_unmap(fdtbus_bs_tag, ram, RAM_SIZE);
}
#if defined(SOC_ALTERA_ARRIA10)
void
socfpga_a10_mp_start_ap(platform_t plat)
{
_socfpga_mp_start_ap(SOCFPGA_ARRIA10);
}
#endif
#if defined(SOC_ALTERA_CYCLONE5)
void
socfpga_mp_start_ap(platform_t plat)
{
_socfpga_mp_start_ap(SOCFPGA_CYCLONE5);
}
#endif

View File

@ -30,5 +30,6 @@
void socfpga_mp_setmaxid(platform_t);
void socfpga_mp_start_ap(platform_t);
void socfpga_a10_mp_start_ap(platform_t);
#endif /* _SOCFPGA_MP_H_ */

View File

@ -1,5 +1,5 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2014-2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
@ -166,7 +166,7 @@ rstmgr_sysctl(SYSCTL_HANDLER_ARGS)
}
int
rstmgr_warmreset(void)
rstmgr_warmreset(uint32_t reg)
{
struct rstmgr_softc *sc;
@ -175,8 +175,7 @@ rstmgr_warmreset(void)
return (1);
/* Request warm reset */
WRITE4(sc, RSTMGR_CTRL,
CTRL_SWWARMRSTREQ);
WRITE4(sc, reg, CTRL_SWWARMRSTREQ);
return (0);
}
@ -214,6 +213,7 @@ rstmgr_probe(device_t dev)
return (ENXIO);
device_set_desc(dev, "Reset Manager");
return (BUS_PROBE_DEFAULT);
}

View File

@ -35,6 +35,7 @@
#define CTRL_SWWARMRSTREQ (1 << 1) /* Trigger warm reset */
#define RSTMGR_COUNTS 0x8 /* Reset Cycles Count */
#define RSTMGR_MPUMODRST 0x10 /* MPU Module Reset */
#define MPUMODRST_CPU1 (1 << 1)
#define RSTMGR_PERMODRST 0x14 /* Peripheral Module Reset */
#define RSTMGR_PER2MODRST 0x18 /* Peripheral 2 Module Reset */
#define RSTMGR_BRGMODRST 0x1C /* Bridge Module Reset */
@ -43,4 +44,7 @@
#define BRGMODRST_HPS2FPGA (1 << 0)
#define RSTMGR_MISCMODRST 0x20 /* Miscellaneous Module Reset */
int rstmgr_warmreset(void);
#define RSTMGR_A10_CTRL 0xC /* Control */
#define RSTMGR_A10_MPUMODRST 0x20 /* MPU Module Reset */
int rstmgr_warmreset(uint32_t reg);

View File

@ -104,7 +104,7 @@ usart_at91_probe(device_t dev)
sc->sc_class = &at91_usart_class;
if (sc->sc_class->uc_rclk == 0)
sc->sc_class->uc_rclk = at91_master_clock;
return (uart_bus_probe(dev, 0, 0, 0, device_get_unit(dev)));
return (uart_bus_probe(dev, 0, 0, 0, 0, device_get_unit(dev)));
}

View File

@ -69,7 +69,7 @@ uart_ec_probe(device_t dev)
sc = device_get_softc(dev);
sc->sc_class = &uart_ns8250_class;
status = uart_bus_probe(dev, EC_UART_REGSHIFT, EC_UART_CLOCK, 0, 0);
status = uart_bus_probe(dev, EC_UART_REGSHIFT, 0, EC_UART_CLOCK, 0, 0);
return (status);
}

30
sys/arm/conf/SOCDK Normal file
View File

@ -0,0 +1,30 @@
#
# Kernel configuration for Altera Arria10 SOC Development Kit.
#
# For more information on this file, please read the config(5) manual page,
# and/or the handbook section on Kernel Configuration Files:
#
# http://www.FreeBSD.org/doc/en_US.ISO8859-1/books/handbook/kernelconfig-config.html
#
# The handbook is also available locally in /usr/share/doc/handbook
# if you've installed the doc distribution, otherwise always see the
# FreeBSD World Wide Web server (http://www.FreeBSD.org/) for the
# latest information.
#
# An exhaustive list of options and more detailed explanations of the
# device lines is also present in the ../../conf/NOTES and NOTES files.
# If you are in doubt as to the purpose or necessity of a line, check first
# in NOTES.
#
# $FreeBSD$
#NO_UNIVERSE
include "SOCFPGA"
ident SOCDK
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
# Flattened Device Tree
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=socfpga_arria10_socdk_sdmmc.dts

View File

@ -1,5 +1,5 @@
#
# Kernel configuration for Terasic SoCKit (Altera Cyclone V SoC).
# Kernel configuration for Altera SOCFPGA development kits.
#
# For more information on this file, please read the config(5) manual page,
# and/or the handbook section on Kernel Configuration Files:
@ -18,6 +18,7 @@
#
# $FreeBSD$
ident SOCFPGA
include "std.armv6"
include "../altera/socfpga/std.socfpga"
@ -29,6 +30,10 @@ options SCHED_ULE # ULE scheduler
options PLATFORM # Platform based SoC
options PLATFORM_SMP
options SMP # Enable multiple cores
options MULTIDELAY
options SOC_ALTERA_ARRIA10
options SOC_ALTERA_CYCLONE5
# NFS root from boopt/dhcp
#options BOOTP
@ -60,7 +65,6 @@ device gpio
# USB support
options USB_HOST_ALIGN=64 # Align usb buffers to cache line size.
device usb
#device musb
device dwcotg
device umass
@ -70,7 +74,7 @@ device pass
# Serial ports
device uart
device uart_ns8250
device uart_snps
# I2C (TWSI)
device iic

View File

@ -20,11 +20,11 @@
#NO_UNIVERSE
include "SOCFPGA"
ident SOCKIT
include "SOCKIT.common"
options ROOTDEVNAME=\"ufs:/dev/da0\"
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
# Flattened Device Tree
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=socfpga-sockit.dts
makeoptions FDT_DTS_FILE=socfpga_cyclone5_sockit_sdmmc.dts

View File

@ -18,8 +18,10 @@
#
# $FreeBSD$
#NO_UNIVERSE
include "SOCFPGA"
ident SOCKIT-BERI
include "SOCKIT.common"
options ROOTDEVNAME=\"ufs:/dev/mmcsd0s4\"
@ -32,4 +34,4 @@ device altera_pio
# Flattened Device Tree
options FDT_DTB_STATIC
makeoptions FDT_DTS_FILE=socfpga-sockit-beri.dts
makeoptions FDT_DTS_FILE=socfpga_cyclone5_sockit_beri_sdmmc.dts

View File

@ -216,7 +216,7 @@ tegra_uart_probe(device_t dev)
device_printf(dev, "Cannot enable UART clock: %d\n", rv);
return (ENXIO);
}
return (uart_bus_probe(dev, shift, (int)freq, 0, 0));
return (uart_bus_probe(dev, shift, 0, (int)freq, 0, 0));
}
static int

View File

@ -83,7 +83,7 @@ uart_i81342_probe(device_t dev)
0x40 | 0x10);
bus_release_resource(dev, sc->sc_rtype, sc->sc_rrid, sc->sc_rres);
err = uart_bus_probe(dev, 2, 33334000, 0, device_get_unit(dev));
err = uart_bus_probe(dev, 2, 0, 33334000, 0, device_get_unit(dev));
sc->sc_rxfifosz = sc->sc_txfifosz = 1;
return (err);
}

View File

@ -78,5 +78,5 @@ uart_ixp425_probe(device_t dev)
if (bootverbose)
device_printf(dev, "rclk %u\n", rclk);
return uart_bus_probe(dev, 0, rclk, 0, 0);
return uart_bus_probe(dev, 0, 0, rclk, 0, 0);
}

View File

@ -97,7 +97,7 @@ uart_pxa_probe(device_t dev)
sc = device_get_softc(dev);
sc->sc_class = &uart_ns8250_class;
return(uart_bus_probe(dev, 2, PXA2X0_COM_FREQ, 0, 0));
return(uart_bus_probe(dev, 2, 0, PXA2X0_COM_FREQ, 0, 0));
}
DRIVER_MODULE(uart, pxa, uart_pxa_driver, uart_devclass, 0, 0);

View File

@ -1,200 +0,0 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/ {
compatible = "altr,socfpga";
#address-cells = <1>;
#size-cells = <1>;
interrupt-parent = <&GIC>;
aliases {
soc = &SOC;
rstmgr = &rstmgr;
l3regs = &l3regs;
serial0 = &serial0;
serial1 = &serial1;
};
SOC: socfpga {
#address-cells = <1>;
#size-cells = <1>;
compatible = "simple-bus";
ranges;
bus-frequency = <0>;
GIC: interrupt-controller@fffed000 {
compatible = "arm,gic";
reg = < 0xfffed000 0x1000 >, /* Distributor */
< 0xfffec100 0x100 >; /* CPU Interface */
interrupt-controller;
#interrupt-cells = <1>;
};
mp_tmr@40002100 {
compatible = "arm,mpcore-timers";
clock-frequency = <200000000>;
#address-cells = <1>;
#size-cells = <0>;
reg = < 0xfffec200 0x100 >, /* Global Timer */
< 0xfffec600 0x100 >; /* Private Timer */
interrupts = < 27 29 >;
interrupt-parent = < &GIC >;
};
sysmgr: sysmgr@ffd08000 {
compatible = "altr,sys-mgr";
reg = <0xffd08000 0x1000>;
};
clkmgr: clkmgr@ffd04000 {
compatible = "altr,clk-mgr";
reg = <0xffd04000 0x1000>;
};
rstmgr: rstmgr@ffd05000 {
compatible = "altr,rst-mgr";
reg = <0xffd05000 0x1000>;
};
l3regs: l3regs@ff800000 {
compatible = "altr,l3regs";
reg = <0xff800000 0x1000>;
};
fpgamgr: fpgamgr@ff706000 {
compatible = "altr,fpga-mgr";
reg = <0xff706000 0x1000>, /* FPGAMGRREGS */
<0xffb90000 0x1000>; /* FPGAMGRDATA */
interrupts = < 207 >;
interrupt-parent = <&GIC>;
};
gpio0: gpio@ff708000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff708000 0x1000>;
porta: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
snps,nr-gpios = <29>;
};
};
gpio1: gpio@ff709000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff709000 0x1000>;
portb: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
snps,nr-gpios = <29>;
};
};
gpio2: gpio@ff70a000 {
compatible = "snps,dw-apb-gpio";
reg = <0xff70a000 0x1000>;
portc: gpio-controller@0 {
compatible = "snps,dw-apb-gpio-port";
gpio-controller;
snps,nr-gpios = <27>;
};
};
serial0: serial@ffc02000 {
compatible = "ns16550";
reg = <0xffc02000 0x1000>;
reg-shift = <2>;
interrupts = <194>;
interrupt-parent = <&GIC>;
current-speed = <115200>;
clock-frequency = < 100000000 >;
status = "disabled";
};
serial1: serial@ffc03000 {
compatible = "ns16550";
reg = <0xffc03000 0x1000>;
reg-shift = <2>;
interrupts = <195>;
interrupt-parent = <&GIC>;
current-speed = <115200>;
clock-frequency = < 100000000 >;
status = "disabled";
};
usb0: usb@ffb00000 {
compatible = "synopsys,designware-hs-otg2";
reg = <0xffb00000 0xffff>;
interrupts = <157>;
interrupt-parent = <&GIC>;
status = "disabled";
};
usb1: usb@ffb40000 {
compatible = "synopsys,designware-hs-otg2";
reg = <0xffb40000 0xffff>;
interrupts = <160>;
interrupt-parent = <&GIC>;
dr_mode = "host";
status = "disabled";
};
gmac0: ethernet@ff700000 {
compatible = "altr,socfpga-stmmac",
"snps,dwmac-3.70a", "snps,dwmac";
reg = <0xff700000 0x2000>;
interrupts = <147>;
interrupt-parent = <&GIC>;
phy-mode = "rgmii";
status = "disabled";
};
gmac1: ethernet@ff702000 {
compatible = "altr,socfpga-stmmac",
"snps,dwmac-3.70a", "snps,dwmac";
reg = <0xff702000 0x2000>;
interrupts = <152>;
interrupt-parent = <&GIC>;
phy-mode = "rgmii";
status = "disabled";
};
mmc: dwmmc@ff704000 {
compatible = "altr,socfpga-dw-mshc";
reg = <0xff704000 0x1000>;
interrupts = <171>;
interrupt-parent = <&GIC>;
fifo-depth = <0x400>;
status = "disabled";
};
};
};

View File

@ -0,0 +1,82 @@
/*-
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
* $FreeBSD$
*/
/dts-v1/;
#include "socfpga_arria10_socdk.dtsi"
/ {
model = "Altera SOCFPGA Arria 10";
compatible = "altr,socfpga-arria10", "altr,socfpga";
/* Reserve first page for secondary CPU trampoline code */
memreserve = < 0x00000000 0x1000 >;
soc {
/* Local timer */
timer@ffffc600 {
clock-frequency = <200000000>;
};
/* Global timer */
global_timer: timer@ffffc200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xffffc200 0x20>;
interrupts = <1 11 0x301>;
clock-frequency = <200000000>;
};
};
chosen {
stdin = "serial1";
stdout = "serial1";
};
};
&uart1 {
clock-frequency = < 50000000 >;
};
&mmc {
status = "okay";
num-slots = <1>;
cap-sd-highspeed;
broken-cd;
bus-width = <4>;
bus-frequency = <200000000>;
};
&i2c1 {
lcd@28 {
compatible = "newhaven,nhd-0216k3z-nsw-bbw";
reg = <0x28>;
};
};

View File

@ -1,9 +1,9 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
@ -30,58 +30,29 @@
* $FreeBSD$
*/
/dts-v1/;
/include/ "socfpga.dtsi"
/* /dts-v1/; */
#include "socfpga_cyclone5_sockit.dts"
/ {
model = "Terasic SoCKit";
model = "Terasic SoCkit";
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
memreserve = < 0x00000000 0x1000 >, /* SMP trampoline */
< 0x00001000 0x1000 >, /* virtio block */
< 0x00002000 0x1000 >; /* virtio net */
memory {
device_type = "memory";
reg = < 0x00000000 0x40000000 >; /* 1G RAM */
};
SOC: socfpga {
serial0: serial@ffc02000 {
status = "okay";
soc {
/* Local timer */
timer@fffec600 {
clock-frequency = <200000000>;
};
usb1: usb@ffb40000 {
status = "okay";
};
gmac1: ethernet@ff702000 {
status = "okay";
rxd0-skew-ps = <0>;
rxd1-skew-ps = <0>;
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
txc-skew-ps = <2600>;
rxdv-skew-ps = <0>;
rxc-skew-ps = <2000>;
};
mmc: dwmmc@ff704000 {
#address-cells = <1>;
#size-cells = <0>;
status = "okay";
num-slots = <1>;
supports-highspeed;
broken-cd;
bus-frequency = <25000000>;
slot@0 {
reg = <0>;
bus-width = <4>;
};
/* Global timer */
global_timer: timer@fffec200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xfffec200 0x20>;
interrupts = <1 11 0xf04>;
clock-frequency = <200000000>;
};
beri_mem0: mem@d0000000 {
@ -94,7 +65,6 @@
compatible = "altr,pio";
reg = <0xc0020000 0x1000>; /* recv */
interrupts = < 76 >;
interrupt-parent = <&GIC>;
status = "okay";
};
@ -102,7 +72,6 @@
compatible = "altr,pio";
reg = <0xc0021000 0x1000>; /* send */
interrupts = < 82 >; /* not in use on arm side */
interrupt-parent = <&GIC>;
status = "okay";
};
@ -110,7 +79,6 @@
compatible = "altr,pio";
reg = <0xc0022000 0x1000>; /* recv */
interrupts = < 77 >;
interrupt-parent = <&GIC>;
status = "okay";
};
@ -118,7 +86,6 @@
compatible = "altr,pio";
reg = <0xc0023000 0x1000>; /* send */
interrupts = < 83 >; /* not in use on arm side */
interrupt-parent = <&GIC>;
status = "okay";
};
@ -144,7 +111,6 @@
compatible = "sri-cambridge,beri-ring";
reg = <0xc0000000 0x3000>;
interrupts = < 72 73 >;
interrupt-parent = <&GIC>;
device_name = "beri_debug";
data_size = <0x1000>;
data_read = <0x0>;
@ -158,7 +124,6 @@
compatible = "sri-cambridge,beri-ring";
reg = <0xc0004000 0x3000>;
interrupts = < 74 75 >;
interrupt-parent = <&GIC>;
device_name = "beri_console";
data_size = <0x1000>;
data_read = <0x0>;
@ -170,8 +135,19 @@
};
chosen {
bootargs = "-v";
stdin = "serial0";
stdout = "serial0";
};
};
&mmc0 {
bus-frequency = <25000000>;
};
&uart0 {
clock-frequency = <100000000>;
};
&uart1 {
status = "disabled";
};

View File

@ -1,9 +1,9 @@
/*-
* Copyright (c) 2014 Ruslan Bukin <br@bsdpad.com>
* Copyright (c) 2017 Ruslan Bukin <br@bsdpad.com>
* All rights reserved.
*
* This software was developed by SRI International and the University of
* Cambridge Computer Laboratory under DARPA/AFRL contract (FA8750-10-C-0237)
* Cambridge Computer Laboratory under DARPA/AFRL contract FA8750-10-C-0237
* ("CTSRD"), as part of the DARPA CRASH research programme.
*
* Redistribution and use in source and binary forms, with or without
@ -30,61 +30,45 @@
* $FreeBSD$
*/
/dts-v1/;
/include/ "socfpga.dtsi"
/* /dts-v1/; */
#include "socfpga_cyclone5_sockit.dts"
/ {
model = "Terasic SoCKit";
model = "Terasic SoCkit";
compatible = "altr,socfpga-cyclone5", "altr,socfpga";
/* Reserve first page for secondary CPU trampoline code */
memreserve = < 0x00000000 0x1000 >;
memory {
device_type = "memory";
reg = < 0x00000000 0x40000000 >; /* 1G RAM */
};
SOC: socfpga {
serial0: serial@ffc02000 {
status = "okay";
soc {
/* Local timer */
timer@fffec600 {
clock-frequency = <200000000>;
};
usb1: usb@ffb40000 {
status = "okay";
};
gmac1: ethernet@ff702000 {
status = "okay";
rxd0-skew-ps = <0>;
rxd1-skew-ps = <0>;
rxd2-skew-ps = <0>;
rxd3-skew-ps = <0>;
txen-skew-ps = <0>;
txc-skew-ps = <2600>;
rxdv-skew-ps = <0>;
rxc-skew-ps = <2000>;
};
mmc: dwmmc@ff704000 {
status = "okay";
num-slots = <1>;
supports-highspeed;
broken-cd;
bus-frequency = <25000000>;
slot@0 {
reg = <0>;
bus-width = <4>;
};
/* Global timer */
global_timer: timer@fffec200 {
compatible = "arm,cortex-a9-global-timer";
reg = <0xfffec200 0x20>;
interrupts = <1 11 0xf04>;
clock-frequency = <200000000>;
};
};
chosen {
bootargs = "-v";
stdin = "serial0";
stdout = "serial0";
};
};
&mmc0 {
bus-frequency = <25000000>;
};
&uart0 {
clock-frequency = <100000000>;
};
&uart1 {
status = "disabled";
};

View File

@ -273,8 +273,6 @@ cloudabi64_load="NO" # 64-bit CloudABI executables support
ibcs2_load="NO" # IBCS2 (SCO) emulation
ibcs2_coff_load="NO"
linux_load="NO" # Linux emulation
svr4_load="NO" # SystemV R4 emulation
streams_load="NO" # System V streams module
##############################################################

View File

@ -25,7 +25,6 @@ BOOT2_UFS?= UFS1_AND_UFS2
CFLAGS= -fomit-frame-pointer \
-mrtd \
-mregparm=3 \
-DUSE_XREAD \
-D${BOOT2_UFS} \
-DFLAGS=${BOOT_BOOT1_FLAGS} \
-DSIOPRT=${BOOT_COMCONSOLE_PORT} \

View File

@ -25,9 +25,6 @@ __FBSDID("$FreeBSD$");
#include "util.h"
#include "drv.h"
#include "edd.h"
#ifdef USE_XREAD
#include "xreadorg.h"
#endif
static struct edd_params params;
@ -50,9 +47,7 @@ drvsize(struct dsk *dskp)
return (params.sectors);
}
#ifndef USE_XREAD
static struct edd_packet packet;
#endif
int
drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
@ -61,7 +56,6 @@ drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
if (!OPT_CHECK(RBX_QUIET))
printf("%c\b", c = c << 8 | c >> 24);
#ifndef USE_XREAD
packet.len = sizeof(struct edd_packet);
packet.count = nblk;
packet.off = VTOPOFF(buf);
@ -73,15 +67,6 @@ drvread(struct dsk *dskp, void *buf, daddr_t lba, unsigned nblk)
v86.edx = dskp->drive;
v86.ds = VTOPSEG(&packet);
v86.esi = VTOPOFF(&packet);
#else /* USE_XREAD */
v86.ctl = V86_ADDR | V86_CALLF | V86_FLAGS;
v86.addr = XREADORG; /* call to xread in boot1 */
v86.es = VTOPSEG(buf);
v86.eax = lba;
v86.ebx = VTOPOFF(buf);
v86.ecx = lba >> 32;
v86.edx = nblk << 8 | dskp->drive;
#endif /* USE_XREAD */
v86int();
if (V86_CY(v86.efl)) {
printf("%s: error %u lba %u\n",

View File

@ -27,6 +27,8 @@
* SUCH DAMAGE.
*/
#include "opt_printf.h"
#include <sys/cdefs.h>
__FBSDID("$FreeBSD$");
@ -72,6 +74,15 @@ __FBSDID("$FreeBSD$");
#include "opt_cam.h"
/* Wild guess based on not wanting to grow the stack too much */
#define XPT_PRINT_MAXLEN 512
#ifdef PRINTF_BUFR_SIZE
#define XPT_PRINT_LEN PRINTF_BUFR_SIZE
#else
#define XPT_PRINT_LEN 128
#endif
_Static_assert(XPT_PRINT_LEN <= XPT_PRINT_MAXLEN, "XPT_PRINT_LEN is too large");
/*
* This is the maximum number of high powered commands (e.g. start unit)
* that can be outstanding at a particular time.

View File

@ -34,7 +34,6 @@
#ifdef _KERNEL
#include <sys/cdefs.h>
#include "opt_printf.h"
#endif
/* Forward Declarations */
@ -55,15 +54,6 @@ struct cam_path;
#ifdef _KERNEL
/* Wild guess based on not wanting to grow the stack too much */
#define XPT_PRINT_MAXLEN 512
#ifdef PRINTF_BUFR_SIZE
#define XPT_PRINT_LEN PRINTF_BUFR_SIZE
#else
#define XPT_PRINT_LEN 128
#endif
_Static_assert(XPT_PRINT_LEN <= XPT_PRINT_MAXLEN, "XPT_PRINT_LEN is too large");
/*
* Definition of an async handler callback block. These are used to add
* SIMs and peripherals to the async callback lists.

View File

@ -478,15 +478,15 @@ static int ctl_scsiio_precheck(struct ctl_softc *ctl_softc,
struct ctl_scsiio *ctsio);
static int ctl_scsiio(struct ctl_scsiio *ctsio);
static int ctl_bus_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
static int ctl_target_reset(struct ctl_softc *ctl_softc, union ctl_io *io,
ctl_ua_type ua_type);
static int ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io,
static int ctl_target_reset(union ctl_io *io);
static void ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx,
ctl_ua_type ua_type);
static int ctl_lun_reset(struct ctl_softc *ctl_softc, union ctl_io *io);
static int ctl_lun_reset(union ctl_io *io);
static int ctl_abort_task(union ctl_io *io);
static int ctl_abort_task_set(union ctl_io *io);
static int ctl_query_task(union ctl_io *io, int task_set);
static void ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
ctl_ua_type ua_type);
static int ctl_i_t_nexus_reset(union ctl_io *io);
static int ctl_query_async_event(union ctl_io *io);
static void ctl_run_task(union ctl_io *io);
@ -1288,6 +1288,9 @@ ctl_isc_iid_sync(struct ctl_softc *softc, union ctl_ha_msg *msg, int len)
return;
}
iid = msg->hdr.nexus.initid;
if (port->wwpn_iid[iid].in_use != 0 &&
msg->iid.in_use == 0)
ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
port->wwpn_iid[iid].in_use = msg->iid.in_use;
port->wwpn_iid[iid].wwpn = msg->iid.wwpn;
free(port->wwpn_iid[iid].name, M_CTL);
@ -2027,6 +2030,7 @@ int
ctl_remove_initiator(struct ctl_port *port, int iid)
{
struct ctl_softc *softc = port->ctl_softc;
int last;
mtx_assert(&softc->ctl_lock, MA_NOTOWNED);
@ -2037,9 +2041,11 @@ ctl_remove_initiator(struct ctl_port *port, int iid)
}
mtx_lock(&softc->ctl_lock);
port->wwpn_iid[iid].in_use--;
last = (--port->wwpn_iid[iid].in_use == 0);
port->wwpn_iid[iid].last_use = time_uptime;
mtx_unlock(&softc->ctl_lock);
if (last)
ctl_i_t_nexus_loss(softc, iid, CTL_UA_POWERON);
ctl_isc_announce_iid(port, iid);
return (0);
@ -2144,11 +2150,6 @@ ctl_add_initiator(struct ctl_port *port, int iid, uint64_t wwpn, char *name)
__func__, port->targ_port, iid, wwpn, name,
(uintmax_t)port->wwpn_iid[iid].wwpn,
port->wwpn_iid[iid].name);
/*
* XXX KDM clear pending_sense and pending_ua on each LUN
* for this initiator.
*/
}
take:
free(port->wwpn_iid[iid].name, M_CTL);
@ -11603,50 +11604,42 @@ ctl_scsiio(struct ctl_scsiio *ctsio)
return (retval);
}
/*
* Since we only implement one target right now, a bus reset simply resets
* our single target.
*/
static int
ctl_bus_reset(struct ctl_softc *softc, union ctl_io *io)
{
return(ctl_target_reset(softc, io, CTL_UA_BUS_RESET));
}
static int
ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
ctl_ua_type ua_type)
ctl_target_reset(union ctl_io *io)
{
struct ctl_softc *softc = CTL_SOFTC(io);
struct ctl_port *port = CTL_PORT(io);
struct ctl_lun *lun;
int retval;
uint32_t initidx;
ctl_ua_type ua_type;
if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
union ctl_ha_msg msg_info;
msg_info.hdr.nexus = io->io_hdr.nexus;
if (ua_type==CTL_UA_TARG_RESET)
msg_info.task.task_action = CTL_TASK_TARGET_RESET;
else
msg_info.task.task_action = CTL_TASK_BUS_RESET;
msg_info.task.task_action = io->taskio.task_action;
msg_info.hdr.msg_type = CTL_MSG_MANAGE_TASKS;
msg_info.hdr.original_sc = NULL;
msg_info.hdr.serializing_sc = NULL;
ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
sizeof(msg_info.task), M_WAITOK);
}
retval = 0;
initidx = ctl_get_initindex(&io->io_hdr.nexus);
if (io->taskio.task_action == CTL_TASK_TARGET_RESET)
ua_type = CTL_UA_TARG_RESET;
else
ua_type = CTL_UA_BUS_RESET;
mtx_lock(&softc->ctl_lock);
STAILQ_FOREACH(lun, &softc->lun_list, links) {
if (port != NULL &&
ctl_lun_map_to_port(port, lun->lun) == UINT32_MAX)
continue;
retval += ctl_do_lun_reset(lun, io, ua_type);
ctl_do_lun_reset(lun, initidx, ua_type);
}
mtx_unlock(&softc->ctl_lock);
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
return (retval);
return (0);
}
/*
@ -11670,66 +11663,51 @@ ctl_target_reset(struct ctl_softc *softc, union ctl_io *io,
*
* XXX KDM for now, we're setting unit attention for all initiators.
*/
static int
ctl_do_lun_reset(struct ctl_lun *lun, union ctl_io *io, ctl_ua_type ua_type)
static void
ctl_do_lun_reset(struct ctl_lun *lun, uint32_t initidx, ctl_ua_type ua_type)
{
union ctl_io *xio;
#if 0
uint32_t initidx;
#endif
int i;
mtx_lock(&lun->lun_lock);
/*
* Run through the OOA queue and abort each I/O.
*/
/* Abort tasks. */
for (xio = (union ctl_io *)TAILQ_FIRST(&lun->ooa_queue); xio != NULL;
xio = (union ctl_io *)TAILQ_NEXT(&xio->io_hdr, ooa_links)) {
xio->io_hdr.flags |= CTL_FLAG_ABORT | CTL_FLAG_ABORT_STATUS;
}
/*
* This version sets unit attention for every
*/
#if 0
initidx = ctl_get_initindex(&io->io_hdr.nexus);
ctl_est_ua_all(lun, initidx, ua_type);
#else
ctl_est_ua_all(lun, -1, ua_type);
#endif
/*
* A reset (any kind, really) clears reservations established with
* RESERVE/RELEASE. It does not clear reservations established
* with PERSISTENT RESERVE OUT, but we don't support that at the
* moment anyway. See SPC-2, section 5.6. SPC-3 doesn't address
* reservations made with the RESERVE/RELEASE commands, because
* those commands are obsolete in SPC-3.
*/
lun->flags &= ~CTL_LUN_RESERVED;
/* Clear CA. */
for (i = 0; i < CTL_MAX_PORTS; i++) {
free(lun->pending_sense[i], M_CTL);
lun->pending_sense[i] = NULL;
}
lun->prevent_count = 0;
/* Clear reservation. */
lun->flags &= ~CTL_LUN_RESERVED;
/* Clear prevent media removal. */
if (lun->prevent) {
for (i = 0; i < CTL_MAX_INITIATORS; i++)
ctl_clear_mask(lun->prevent, i);
lun->prevent_count = 0;
}
/* Clear TPC status */
ctl_tpc_lun_clear(lun, -1);
/* Establish UA. */
#if 0
ctl_est_ua_all(lun, initidx, ua_type);
#else
ctl_est_ua_all(lun, -1, ua_type);
#endif
mtx_unlock(&lun->lun_lock);
return (0);
}
static int
ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
ctl_lun_reset(union ctl_io *io)
{
struct ctl_softc *softc = CTL_SOFTC(io);
struct ctl_lun *lun;
uint32_t targ_lun;
int retval;
uint32_t targ_lun, initidx;
targ_lun = io->io_hdr.nexus.targ_mapped_lun;
initidx = ctl_get_initindex(&io->io_hdr.nexus);
mtx_lock(&softc->ctl_lock);
if (targ_lun >= CTL_MAX_LUNS ||
(lun = softc->ctl_luns[targ_lun]) == NULL) {
@ -11737,7 +11715,7 @@ ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
io->taskio.task_status = CTL_TASK_LUN_DOES_NOT_EXIST;
return (1);
}
retval = ctl_do_lun_reset(lun, io, CTL_UA_LUN_RESET);
ctl_do_lun_reset(lun, initidx, CTL_UA_LUN_RESET);
mtx_unlock(&softc->ctl_lock);
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
@ -11752,7 +11730,7 @@ ctl_lun_reset(struct ctl_softc *softc, union ctl_io *io)
ctl_ha_msg_send(CTL_HA_CHAN_CTL, &msg_info,
sizeof(msg_info.task), M_WAITOK);
}
return (retval);
return (0);
}
static void
@ -11832,12 +11810,46 @@ ctl_abort_task_set(union ctl_io *io)
return (0);
}
static void
ctl_i_t_nexus_loss(struct ctl_softc *softc, uint32_t initidx,
ctl_ua_type ua_type)
{
struct ctl_lun *lun;
struct scsi_sense_data *ps;
uint32_t p, i;
p = initidx / CTL_MAX_INIT_PER_PORT;
i = initidx % CTL_MAX_INIT_PER_PORT;
mtx_lock(&softc->ctl_lock);
STAILQ_FOREACH(lun, &softc->lun_list, links) {
mtx_lock(&lun->lun_lock);
/* Abort tasks. */
ctl_abort_tasks_lun(lun, p, i, 1);
/* Clear CA. */
ps = lun->pending_sense[p];
if (ps != NULL)
ps[i].error_code = 0;
/* Clear reservation. */
if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
lun->flags &= ~CTL_LUN_RESERVED;
/* Clear prevent media removal. */
if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
ctl_clear_mask(lun->prevent, initidx);
lun->prevent_count--;
}
/* Clear TPC status */
ctl_tpc_lun_clear(lun, initidx);
/* Establish UA. */
ctl_est_ua(lun, initidx, ua_type);
mtx_unlock(&lun->lun_lock);
}
mtx_unlock(&softc->ctl_lock);
}
static int
ctl_i_t_nexus_reset(union ctl_io *io)
{
struct ctl_softc *softc = CTL_SOFTC(io);
struct ctl_lun *lun;
struct scsi_sense_data *ps;
uint32_t initidx;
if (!(io->io_hdr.flags & CTL_FLAG_FROM_OTHER_SC)) {
@ -11853,24 +11865,7 @@ ctl_i_t_nexus_reset(union ctl_io *io)
}
initidx = ctl_get_initindex(&io->io_hdr.nexus);
mtx_lock(&softc->ctl_lock);
STAILQ_FOREACH(lun, &softc->lun_list, links) {
mtx_lock(&lun->lun_lock);
ctl_abort_tasks_lun(lun, io->io_hdr.nexus.targ_port,
io->io_hdr.nexus.initid, 1);
ps = lun->pending_sense[initidx / CTL_MAX_INIT_PER_PORT];
if (ps != NULL)
ps[initidx % CTL_MAX_INIT_PER_PORT].error_code = 0;
if ((lun->flags & CTL_LUN_RESERVED) && (lun->res_idx == initidx))
lun->flags &= ~CTL_LUN_RESERVED;
if (lun->prevent && ctl_is_set(lun->prevent, initidx)) {
ctl_clear_mask(lun->prevent, initidx);
lun->prevent_count--;
}
ctl_est_ua(lun, initidx, CTL_UA_I_T_NEXUS_LOSS);
mtx_unlock(&lun->lun_lock);
}
mtx_unlock(&softc->ctl_lock);
ctl_i_t_nexus_loss(softc, initidx, CTL_UA_I_T_NEXUS_LOSS);
io->taskio.task_status = CTL_TASK_FUNCTION_COMPLETE;
return (0);
}
@ -12079,7 +12074,6 @@ ctl_query_async_event(union ctl_io *io)
static void
ctl_run_task(union ctl_io *io)
{
struct ctl_softc *softc = CTL_SOFTC(io);
int retval = 1;
CTL_DEBUG_PRINT(("ctl_run_task\n"));
@ -12101,13 +12095,11 @@ ctl_run_task(union ctl_io *io)
retval = ctl_i_t_nexus_reset(io);
break;
case CTL_TASK_LUN_RESET:
retval = ctl_lun_reset(softc, io);
retval = ctl_lun_reset(io);
break;
case CTL_TASK_TARGET_RESET:
retval = ctl_target_reset(softc, io, CTL_UA_TARG_RESET);
break;
case CTL_TASK_BUS_RESET:
retval = ctl_bus_reset(softc, io);
retval = ctl_target_reset(io);
break;
case CTL_TASK_PORT_LOGIN:
break;
@ -13154,21 +13146,15 @@ ctl_queue_sense(union ctl_io *io)
initidx = ctl_get_initindex(&io->io_hdr.nexus);
p = initidx / CTL_MAX_INIT_PER_PORT;
if ((ps = lun->pending_sense[p]) == NULL) {
mtx_unlock(&lun->lun_lock);
ps = malloc(sizeof(*ps) * CTL_MAX_INIT_PER_PORT, M_CTL,
M_WAITOK | M_ZERO);
mtx_lock(&lun->lun_lock);
if (lun->pending_sense[p] == NULL) {
lun->pending_sense[p] = ps;
} else {
free(ps, M_CTL);
ps = lun->pending_sense[p];
}
if (lun->pending_sense[p] == NULL) {
lun->pending_sense[p] = malloc(sizeof(*ps) * CTL_MAX_INIT_PER_PORT,
M_CTL, M_NOWAIT | M_ZERO);
}
if ((ps = lun->pending_sense[p]) != NULL) {
ps += initidx % CTL_MAX_INIT_PER_PORT;
memset(ps, 0, sizeof(*ps));
memcpy(ps, &io->scsiio.sense_data, io->scsiio.sense_len);
}
ps += initidx % CTL_MAX_INIT_PER_PORT;
memset(ps, 0, sizeof(*ps));
memcpy(ps, &io->scsiio.sense_data, io->scsiio.sense_len);
mtx_unlock(&lun->lun_lock);
bailout:

View File

@ -528,6 +528,7 @@ int ctl_get_lba_status(struct ctl_scsiio *ctsio);
void ctl_tpc_init(struct ctl_softc *softc);
void ctl_tpc_shutdown(struct ctl_softc *softc);
void ctl_tpc_lun_init(struct ctl_lun *lun);
void ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx);
void ctl_tpc_lun_shutdown(struct ctl_lun *lun);
int ctl_inquiry_evpd_tpc(struct ctl_scsiio *ctsio, int alloc_len);
int ctl_receive_copy_status_lid1(struct ctl_scsiio *ctsio);

View File

@ -221,6 +221,21 @@ ctl_tpc_lun_init(struct ctl_lun *lun)
TAILQ_INIT(&lun->tpc_lists);
}
void
ctl_tpc_lun_clear(struct ctl_lun *lun, uint32_t initidx)
{
struct tpc_list *list, *tlist;
TAILQ_FOREACH_SAFE(list, &lun->tpc_lists, links, tlist) {
if (initidx != -1 && list->init_idx != initidx)
continue;
if (!list->completed)
continue;
TAILQ_REMOVE(&lun->tpc_lists, list, links);
free(list, M_CTL);
}
}
void
ctl_tpc_lun_shutdown(struct ctl_lun *lun)
{

View File

@ -1223,6 +1223,20 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
* datamove done routine.
*/
if ((io->io_hdr.flags & CTL_FLAG_DMA_INPROG) == 0) {
/*
* If we asked to send sense data but it wasn't sent,
* queue the I/O back to CTL for later REQUEST SENSE.
*/
if ((done_ccb->ccb_h.flags & CAM_SEND_SENSE) != 0 &&
(done_ccb->ccb_h.status & CAM_STATUS_MASK) == CAM_REQ_CMP &&
(done_ccb->ccb_h.status & CAM_SENT_SENSE) == 0 &&
(io = ctl_alloc_io_nowait(bus_softc->port.ctl_pool_ref)) != NULL) {
PRIV_INFO(io) = PRIV_INFO(
(union ctl_io *)atio->ccb_h.io_ptr);
ctl_queue_sense(atio->ccb_h.io_ptr);
atio->ccb_h.io_ptr = io;
}
/* Abort ATIO if CTIO sending status has failed. */
if ((done_ccb->ccb_h.status & CAM_STATUS_MASK) !=
CAM_REQ_CMP) {
@ -1253,7 +1267,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
*/
switch (done_ccb->ccb_h.status & CAM_STATUS_MASK) {
case CAM_REQ_CMP:
io->scsiio.kern_data_resid -= csio->dxfer_len;
io->scsiio.kern_data_resid -=
csio->dxfer_len - csio->resid;
io->io_hdr.port_status = 0;
break;
default:
@ -1280,8 +1295,8 @@ ctlfedone(struct cam_periph *periph, union ccb *done_ccb)
* pieces, figure out where we are in the list, and
* continue sending pieces if necessary.
*/
if ((cmd_info->flags & CTLFE_CMD_PIECEWISE)
&& (io->io_hdr.port_status == 0)) {
if ((cmd_info->flags & CTLFE_CMD_PIECEWISE) &&
io->io_hdr.port_status == 0 && csio->resid == 0) {
ccb_flags flags;
uint8_t *data_ptr;
uint32_t dxfer_len;

View File

@ -6897,7 +6897,7 @@ l2arc_evict(l2arc_dev_t *dev, uint64_t distance, boolean_t all)
}
if (!all && HDR_HAS_L2HDR(hdr) &&
(hdr->b_l2hdr.b_daddr > taddr ||
(hdr->b_l2hdr.b_daddr >= taddr ||
hdr->b_l2hdr.b_daddr < dev->l2ad_hand)) {
/*
* We've evicted to the target address,
@ -7031,7 +7031,22 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
continue;
}
if ((write_asize + HDR_GET_LSIZE(hdr)) > target_sz) {
/*
* We rely on the L1 portion of the header below, so
* it's invalid for this header to have been evicted out
* of the ghost cache, prior to being written out. The
* ARC_FLAG_L2_WRITING bit ensures this won't happen.
*/
ASSERT(HDR_HAS_L1HDR(hdr));
ASSERT3U(HDR_GET_PSIZE(hdr), >, 0);
ASSERT3P(hdr->b_l1hdr.b_pdata, !=, NULL);
ASSERT3U(arc_hdr_size(hdr), >, 0);
uint64_t size = arc_hdr_size(hdr);
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
size);
if ((write_psize + asize) > target_sz) {
full = B_TRUE;
mutex_exit(hash_lock);
ARCSTAT_BUMP(arcstat_l2_write_full);
@ -7066,21 +7081,6 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
list_insert_head(&dev->l2ad_buflist, hdr);
mutex_exit(&dev->l2ad_mtx);
/*
* We rely on the L1 portion of the header below, so
* it's invalid for this header to have been evicted out
* of the ghost cache, prior to being written out. The
* ARC_FLAG_L2_WRITING bit ensures this won't happen.
*/
ASSERT(HDR_HAS_L1HDR(hdr));
ASSERT3U(HDR_GET_PSIZE(hdr), >, 0);
ASSERT3P(hdr->b_l1hdr.b_pdata, !=, NULL);
ASSERT3U(arc_hdr_size(hdr), >, 0);
uint64_t size = arc_hdr_size(hdr);
uint64_t asize = vdev_psize_to_asize(dev->l2ad_vdev,
size);
(void) refcount_add_many(&dev->l2ad_alloc, size, hdr);
/*
@ -7142,7 +7142,7 @@ l2arc_write_buffers(spa_t *spa, l2arc_dev_t *dev, uint64_t target_sz)
return (0);
}
ASSERT3U(write_asize, <=, target_sz);
ASSERT3U(write_psize, <=, target_sz);
ARCSTAT_BUMP(arcstat_l2_writes_sent);
ARCSTAT_INCR(arcstat_l2_write_bytes, write_asize);
ARCSTAT_INCR(arcstat_l2_size, write_sz);

View File

@ -174,10 +174,6 @@ uint_t zio_taskq_basedc = 80; /* base duty cycle */
boolean_t spa_create_process = B_TRUE; /* no process ==> no sysdc */
extern int zfs_sync_pass_deferred_free;
#ifndef illumos
extern void spa_deadman(void *arg);
#endif
/*
* This (illegal) pool name is used when temporarily importing a spa_t in order
* to get the vdev stats associated with the imported devices.
@ -6883,8 +6879,8 @@ spa_sync(spa_t *spa, uint64_t txg)
spa->spa_sync_starttime + spa->spa_deadman_synctime));
#else /* !illumos */
#ifdef _KERNEL
callout_reset(&spa->spa_deadman_cycid,
hz * spa->spa_deadman_synctime / NANOSEC, spa_deadman, spa);
callout_schedule(&spa->spa_deadman_cycid,
hz * spa->spa_deadman_synctime / NANOSEC);
#endif
#endif /* illumos */

View File

@ -597,8 +597,8 @@ spa_lookup(const char *name)
* If the zfs_deadman_enabled flag is set then it inspects all vdev queues
* looking for potentially hung I/Os.
*/
void
spa_deadman(void *arg)
static void
spa_deadman(void *arg, int pending)
{
spa_t *spa = arg;
@ -627,6 +627,16 @@ spa_deadman(void *arg)
#endif
}
#if defined(__FreeBSD__) && defined(_KERNEL)
static void
spa_deadman_timeout(void *arg)
{
spa_t *spa = arg;
taskqueue_enqueue(taskqueue_thread, &spa->spa_deadman_task);
}
#endif
/*
* Create an uninitialized spa_t with the given name. Requires
* spa_namespace_lock. The caller must ensure that the spa_t doesn't already
@ -698,7 +708,23 @@ spa_add(const char *name, nvlist_t *config, const char *altroot)
mutex_exit(&cpu_lock);
#else /* !illumos */
#ifdef _KERNEL
/*
* callout(9) does not provide a way to initialize a callout with
* a function and an argument, so we use callout_reset() to schedule
* the callout in the very distant future. Even if that event ever
* fires, it should be okayas we won't have any active zio-s.
* But normally spa_sync() will reschedule the callout with a proper
* timeout.
* callout(9) does not allow the callback function to sleep but
* vdev_deadman() needs to acquire vq_lock and illumos mutexes are
* emulated using sx(9). For this reason spa_deadman_timeout()
* will schedule spa_deadman() as task on a taskqueue that allows
* sleeping.
*/
TASK_INIT(&spa->spa_deadman_task, 0, spa_deadman, spa);
callout_init(&spa->spa_deadman_cycid, 1);
callout_reset_sbt(&spa->spa_deadman_cycid, SBT_MAX, 0,
spa_deadman_timeout, spa, 0);
#endif
#endif
refcount_create(&spa->spa_refcount);
@ -811,6 +837,7 @@ spa_remove(spa_t *spa)
#else /* !illumos */
#ifdef _KERNEL
callout_drain(&spa->spa_deadman_cycid);
taskqueue_drain(taskqueue_thread, &spa->spa_deadman_task);
#endif
#endif

View File

@ -267,6 +267,7 @@ struct spa {
#else /* !illumos */
#ifdef _KERNEL
struct callout spa_deadman_cycid; /* callout id */
struct task spa_deadman_task;
#endif
#endif /* illumos */
uint64_t spa_deadman_calls; /* number of deadman calls */

View File

@ -27,7 +27,7 @@
* Portions Copyright 2010 Robert Milkowski
*
* Copyright 2011 Nexenta Systems, Inc. All rights reserved.
* Copyright (c) 2012, 2014 by Delphix. All rights reserved.
* Copyright (c) 2012, 2016 by Delphix. All rights reserved.
* Copyright (c) 2013, Joyent, Inc. All rights reserved.
* Copyright (c) 2014 Integros [integros.com]
*/
@ -202,11 +202,22 @@ int zvol_maxphys = DMU_MAX_ACCESS/2;
* Toggle unmap functionality.
*/
boolean_t zvol_unmap_enabled = B_TRUE;
/*
* If true, unmaps requested as synchronous are executed synchronously,
* otherwise all unmaps are asynchronous.
*/
boolean_t zvol_unmap_sync_enabled = B_FALSE;
#ifndef illumos
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_enabled, CTLFLAG_RWTUN,
&zvol_unmap_enabled, 0,
"Enable UNMAP functionality");
SYSCTL_INT(_vfs_zfs_vol, OID_AUTO, unmap_sync_enabled, CTLFLAG_RWTUN,
&zvol_unmap_sync_enabled, 0,
"UNMAPs requested as sync are executed synchronously");
static d_open_t zvol_d_open;
static d_close_t zvol_d_close;
static d_read_t zvol_read;
@ -2268,26 +2279,21 @@ zvol_ioctl(dev_t dev, int cmd, intptr_t arg, int flag, cred_t *cr, int *rvalp)
zfs_range_unlock(rl);
if (error == 0) {
/*
* If the write-cache is disabled or 'sync' property
* is set to 'always' then treat this as a synchronous
* operation (i.e. commit to zil).
*/
if (!(zv->zv_flags & ZVOL_WCE) ||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS))
zil_commit(zv->zv_zilog, ZVOL_OBJ);
/*
* If the caller really wants synchronous writes, and
* can't wait for them, don't return until the write
* is done.
*/
if (df.df_flags & DF_WAIT_SYNC) {
txg_wait_synced(
dmu_objset_pool(zv->zv_objset), 0);
}
/*
* If the write-cache is disabled, 'sync' property
* is set to 'always', or if the caller is asking for
* a synchronous free, commit this operation to the zil.
* This will sync any previous uncommitted writes to the
* zvol object.
* Can be overridden by the zvol_unmap_sync_enabled tunable.
*/
if ((error == 0) && zvol_unmap_sync_enabled &&
(!(zv->zv_flags & ZVOL_WCE) ||
(zv->zv_objset->os_sync == ZFS_SYNC_ALWAYS) ||
(df.df_flags & DF_WAIT_SYNC))) {
zil_commit(zv->zv_zilog, ZVOL_OBJ);
}
return (error);
}

View File

@ -37,6 +37,7 @@ __FBSDID("$FreeBSD$");
#include <sys/limits.h>
#include <sys/lock.h>
#include <sys/mutex.h>
#include <sys/callout.h>
#include <sys/capsicum.h>
#include <sys/types.h>
#include <sys/user.h>
@ -63,6 +64,7 @@ __FBSDID("$FreeBSD$");
#include <compat/linux/linux_emul.h>
#include <compat/linux/linux_event.h>
#include <compat/linux/linux_file.h>
#include <compat/linux/linux_timer.h>
#include <compat/linux/linux_util.h>
/*
@ -123,7 +125,6 @@ typedef uint64_t eventfd_t;
static fo_rdwr_t eventfd_read;
static fo_rdwr_t eventfd_write;
static fo_truncate_t eventfd_truncate;
static fo_ioctl_t eventfd_ioctl;
static fo_poll_t eventfd_poll;
static fo_kqfilter_t eventfd_kqfilter;
@ -134,7 +135,7 @@ static fo_fill_kinfo_t eventfd_fill_kinfo;
static struct fileops eventfdops = {
.fo_read = eventfd_read,
.fo_write = eventfd_write,
.fo_truncate = eventfd_truncate,
.fo_truncate = invfo_truncate,
.fo_ioctl = eventfd_ioctl,
.fo_poll = eventfd_poll,
.fo_kqfilter = eventfd_kqfilter,
@ -162,6 +163,41 @@ static struct filterops eventfd_wfiltops = {
.f_event = filt_eventfdwrite
};
/* timerfd */
typedef uint64_t timerfd_t;
static fo_rdwr_t timerfd_read;
static fo_poll_t timerfd_poll;
static fo_kqfilter_t timerfd_kqfilter;
static fo_stat_t timerfd_stat;
static fo_close_t timerfd_close;
static fo_fill_kinfo_t timerfd_fill_kinfo;
static struct fileops timerfdops = {
.fo_read = timerfd_read,
.fo_write = invfo_rdwr,
.fo_truncate = invfo_truncate,
.fo_ioctl = eventfd_ioctl,
.fo_poll = timerfd_poll,
.fo_kqfilter = timerfd_kqfilter,
.fo_stat = timerfd_stat,
.fo_close = timerfd_close,
.fo_chmod = invfo_chmod,
.fo_chown = invfo_chown,
.fo_sendfile = invfo_sendfile,
.fo_fill_kinfo = timerfd_fill_kinfo,
.fo_flags = DFLAG_PASSABLE
};
static void filt_timerfddetach(struct knote *kn);
static int filt_timerfdread(struct knote *kn, long hint);
static struct filterops timerfd_rfiltops = {
.f_isfd = 1,
.f_detach = filt_timerfddetach,
.f_event = filt_timerfdread
};
struct eventfd {
eventfd_t efd_count;
uint32_t efd_flags;
@ -169,7 +205,19 @@ struct eventfd {
struct mtx efd_lock;
};
struct timerfd {
clockid_t tfd_clockid;
struct itimerspec tfd_time;
struct callout tfd_callout;
timerfd_t tfd_count;
bool tfd_canceled;
struct selinfo tfd_sel;
struct mtx tfd_lock;
};
static int eventfd_create(struct thread *td, uint32_t initval, int flags);
static void linux_timerfd_expire(void *);
static void linux_timerfd_curval(struct timerfd *, struct itimerspec *);
static void
@ -207,7 +255,7 @@ epoll_create_common(struct thread *td, int flags)
int error;
error = kern_kqueue(td, flags, NULL);
if (error)
if (error != 0)
return (error);
epoll_fd_install(td, EPOLL_DEF_SZ, 0);
@ -309,14 +357,15 @@ kevent_to_epoll(struct kevent *kevent, struct epoll_event *l_event)
return;
}
/* XXX EPOLLPRI, EPOLLHUP */
switch (kevent->filter) {
case EVFILT_READ:
l_event->events = LINUX_EPOLLIN|LINUX_EPOLLRDNORM|LINUX_EPOLLPRI;
l_event->events = LINUX_EPOLLIN;
if ((kevent->flags & EV_EOF) != 0)
l_event->events |= LINUX_EPOLLRDHUP;
break;
case EVFILT_WRITE:
l_event->events = LINUX_EPOLLOUT|LINUX_EPOLLWRNORM;
l_event->events = LINUX_EPOLLOUT;
break;
}
}
@ -378,7 +427,7 @@ epoll_kev_copyin(void *arg, struct kevent *kevp, int count)
struct epoll_copyin_args *args;
args = (struct epoll_copyin_args*) arg;
memcpy(kevp, args->changelist, count * sizeof(*kevp));
args->changelist += count;
@ -414,8 +463,10 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
cap_rights_init(&rights, CAP_KQUEUE_CHANGE), &epfp);
if (error != 0)
return (error);
if (epfp->f_type != DTYPE_KQUEUE)
if (epfp->f_type != DTYPE_KQUEUE) {
error = EINVAL;
goto leave1;
}
/* Protect user data vector from incorrectly supplied fd. */
error = fget(td, args->fd, cap_rights_init(&rights, CAP_POLL_EVENT), &fp);
@ -430,20 +481,34 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
ciargs.changelist = kev;
if (args->op != LINUX_EPOLL_CTL_DEL) {
kev_flags = EV_ADD | EV_ENABLE;
error = epoll_to_kevent(td, epfp, args->fd, &le,
&kev_flags, kev, &nchanges);
if (error != 0)
goto leave0;
}
switch (args->op) {
case LINUX_EPOLL_CTL_MOD:
/*
* We don't memorize which events were set for this FD
* on this level, so just delete all we could have set:
* EVFILT_READ and EVFILT_WRITE, ignoring any errors
*/
error = epoll_delete_all_events(td, epfp, args->fd);
if (error)
if (error != 0)
goto leave0;
/* FALLTHROUGH */
break;
case LINUX_EPOLL_CTL_ADD:
kev_flags = EV_ADD | EV_ENABLE;
/*
* kqueue_register() return ENOENT if event does not exists
* and the EV_ADD flag is not set.
*/
kev[0].flags &= ~EV_ADD;
error = kqfd_register(args->epfd, &kev[0], td, 1);
if (error != ENOENT) {
error = EEXIST;
goto leave0;
}
error = 0;
kev[0].flags |= EV_ADD;
break;
case LINUX_EPOLL_CTL_DEL:
@ -456,11 +521,6 @@ linux_epoll_ctl(struct thread *td, struct linux_epoll_ctl_args *args)
goto leave0;
}
error = epoll_to_kevent(td, epfp, args->fd, &le, &kev_flags,
kev, &nchanges);
if (error)
goto leave0;
epoll_fd_install(td, args->fd, le.data);
error = kern_kevent_fp(td, epfp, nchanges, 0, &k_ops, NULL);
@ -480,23 +540,32 @@ static int
linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
int maxevents, int timeout, sigset_t *uset)
{
struct file *epfp;
struct timespec ts, *tsp;
cap_rights_t rights;
struct epoll_copyout_args coargs;
struct kevent_copyops k_ops = { &coargs,
epoll_kev_copyout,
NULL};
struct timespec ts, *tsp;
cap_rights_t rights;
struct file *epfp;
sigset_t omask;
int error;
if (maxevents <= 0 || maxevents > LINUX_MAX_EVENTS)
return (EINVAL);
error = fget(td, epfd,
cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
if (error != 0)
return (error);
if (epfp->f_type != DTYPE_KQUEUE) {
error = EINVAL;
goto leave1;
}
if (uset != NULL) {
error = kern_sigprocmask(td, SIG_SETMASK, uset,
&td->td_oldsigmask, 0);
&omask, 0);
if (error != 0)
return (error);
goto leave1;
td->td_pflags |= TDP_OLDMASK;
/*
* Make sure that ast() is called on return to
@ -508,10 +577,6 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
thread_unlock(td);
}
error = fget(td, epfd,
cap_rights_init(&rights, CAP_KQUEUE_EVENT), &epfp);
if (error != 0)
return (error);
coargs.leventlist = events;
coargs.p = td->td_proc;
@ -521,7 +586,7 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
if (timeout != -1) {
if (timeout < 0) {
error = EINVAL;
goto leave;
goto leave0;
}
/* Convert from milliseconds to timespec. */
ts.tv_sec = timeout / 1000;
@ -541,7 +606,12 @@ linux_epoll_wait_common(struct thread *td, int epfd, struct epoll_event *events,
*/
if (error == 0)
td->td_retval[0] = coargs.count;
leave:
leave0:
if (uset != NULL)
error = kern_sigprocmask(td, SIG_SETMASK, &omask,
NULL, 0);
leave1:
fdrop(epfp, td);
return (error);
}
@ -562,6 +632,8 @@ linux_epoll_pwait(struct thread *td, struct linux_epoll_pwait_args *args)
int error;
if (args->mask != NULL) {
if (args->sigsetsize != sizeof(l_sigset_t))
return (EINVAL);
error = copyin(args->mask, &lmask, sizeof(l_sigset_t));
if (error != 0)
return (error);
@ -581,19 +653,11 @@ epoll_delete_event(struct thread *td, struct file *epfp, int fd, int filter)
struct kevent_copyops k_ops = { &ciargs,
NULL,
epoll_kev_copyin};
int error;
ciargs.changelist = &kev;
EV_SET(&kev, fd, filter, EV_DELETE | EV_DISABLE, 0, 0, 0);
error = kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL);
/*
* here we ignore ENONT, because we don't keep track of events here
*/
if (error == ENOENT)
error = 0;
return (error);
return (kern_kevent_fp(td, epfp, 1, 0, &k_ops, NULL));
}
static int
@ -604,8 +668,8 @@ epoll_delete_all_events(struct thread *td, struct file *epfp, int fd)
error1 = epoll_delete_event(td, epfp, fd, EVFILT_READ);
error2 = epoll_delete_event(td, epfp, fd, EVFILT_WRITE);
/* report any errors we got */
return (error1 == 0 ? error2 : error1);
/* return 0 if at least one result positive */
return (error1 == 0 ? 0 : error2);
}
static int
@ -622,7 +686,7 @@ eventfd_create(struct thread *td, uint32_t initval, int flags)
fdp = td->td_proc->p_fd;
error = falloc(td, &fp, &fd, fflags);
if (error)
if (error != 0)
return (error);
efd = malloc(sizeof(*efd), M_EPOLL, M_WAITOK | M_ZERO);
@ -667,7 +731,7 @@ eventfd_close(struct file *fp, struct thread *td)
efd = fp->f_data;
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
return (EBADF);
return (EINVAL);
seldrain(&efd->efd_sel);
knlist_destroy(&efd->efd_sel.si_note);
@ -681,7 +745,7 @@ eventfd_close(struct file *fp, struct thread *td)
static int
eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
int flags, struct thread *td)
int flags, struct thread *td)
{
struct eventfd *efd;
eventfd_t count;
@ -689,7 +753,7 @@ eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
efd = fp->f_data;
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
return (EBADF);
return (EINVAL);
if (uio->uio_resid < sizeof(eventfd_t))
return (EINVAL);
@ -698,7 +762,7 @@ eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
mtx_lock(&efd->efd_lock);
retry:
if (efd->efd_count == 0) {
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
if ((fp->f_flag & FNONBLOCK) != 0) {
mtx_unlock(&efd->efd_lock);
return (EAGAIN);
}
@ -727,7 +791,7 @@ eventfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
static int
eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
int flags, struct thread *td)
int flags, struct thread *td)
{
struct eventfd *efd;
eventfd_t count;
@ -735,13 +799,13 @@ eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
efd = fp->f_data;
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
return (EBADF);
return (EINVAL);
if (uio->uio_resid < sizeof(eventfd_t))
return (EINVAL);
error = uiomove(&count, sizeof(eventfd_t), uio);
if (error)
if (error != 0)
return (error);
if (count == UINT64_MAX)
return (EINVAL);
@ -749,7 +813,7 @@ eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
mtx_lock(&efd->efd_lock);
retry:
if (UINT64_MAX - efd->efd_count <= count) {
if ((efd->efd_flags & LINUX_O_NONBLOCK) != 0) {
if ((fp->f_flag & FNONBLOCK) != 0) {
mtx_unlock(&efd->efd_lock);
/* Do not not return the number of bytes written */
uio->uio_resid += sizeof(eventfd_t);
@ -773,7 +837,7 @@ eventfd_write(struct file *fp, struct uio *uio, struct ucred *active_cred,
static int
eventfd_poll(struct file *fp, int events, struct ucred *active_cred,
struct thread *td)
struct thread *td)
{
struct eventfd *efd;
int revents = 0;
@ -860,33 +924,23 @@ filt_eventfdwrite(struct knote *kn, long hint)
return (ret);
}
/*ARGSUSED*/
static int
eventfd_truncate(struct file *fp, off_t length, struct ucred *active_cred,
struct thread *td)
{
return (ENXIO);
}
/*ARGSUSED*/
static int
eventfd_ioctl(struct file *fp, u_long cmd, void *data,
struct ucred *active_cred, struct thread *td)
struct ucred *active_cred, struct thread *td)
{
struct eventfd *efd;
efd = fp->f_data;
if (fp->f_type != DTYPE_LINUXEFD || efd == NULL)
if (fp->f_data == NULL || (fp->f_type != DTYPE_LINUXEFD &&
fp->f_type != DTYPE_LINUXTFD))
return (EINVAL);
switch (cmd)
{
case FIONBIO:
if (*(int *)data)
efd->efd_flags |= LINUX_O_NONBLOCK;
if ((*(int *)data))
atomic_set_int(&fp->f_flag, FNONBLOCK);
else
efd->efd_flags &= ~LINUX_O_NONBLOCK;
atomic_clear_int(&fp->f_flag, FNONBLOCK);
case FIOASYNC:
return (0);
default:
@ -897,7 +951,7 @@ eventfd_ioctl(struct file *fp, u_long cmd, void *data,
/*ARGSUSED*/
static int
eventfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
struct thread *td)
struct thread *td)
{
return (ENXIO);
@ -911,3 +965,360 @@ eventfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp
kif->kf_type = KF_TYPE_UNKNOWN;
return (0);
}
int
linux_timerfd_create(struct thread *td, struct linux_timerfd_create_args *args)
{
struct filedesc *fdp;
struct timerfd *tfd;
struct file *fp;
clockid_t clockid;
int fflags, fd, error;
if ((args->flags & ~LINUX_TFD_CREATE_FLAGS) != 0)
return (EINVAL);
error = linux_to_native_clockid(&clockid, args->clockid);
if (error != 0)
return (error);
if (clockid != CLOCK_REALTIME && clockid != CLOCK_MONOTONIC)
return (EINVAL);
fflags = 0;
if ((args->flags & LINUX_TFD_CLOEXEC) != 0)
fflags |= O_CLOEXEC;
fdp = td->td_proc->p_fd;
error = falloc(td, &fp, &fd, fflags);
if (error != 0)
return (error);
tfd = malloc(sizeof(*tfd), M_EPOLL, M_WAITOK | M_ZERO);
tfd->tfd_clockid = clockid;
mtx_init(&tfd->tfd_lock, "timerfd", NULL, MTX_DEF);
callout_init_mtx(&tfd->tfd_callout, &tfd->tfd_lock, 0);
knlist_init_mtx(&tfd->tfd_sel.si_note, &tfd->tfd_lock);
fflags = FREAD;
if ((args->flags & LINUX_O_NONBLOCK) != 0)
fflags |= FNONBLOCK;
finit(fp, fflags, DTYPE_LINUXTFD, tfd, &timerfdops);
fdrop(fp, td);
td->td_retval[0] = fd;
return (error);
}
static int
timerfd_close(struct file *fp, struct thread *td)
{
struct timerfd *tfd;
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
return (EINVAL);
timespecclear(&tfd->tfd_time.it_value);
timespecclear(&tfd->tfd_time.it_interval);
mtx_lock(&tfd->tfd_lock);
callout_drain(&tfd->tfd_callout);
mtx_unlock(&tfd->tfd_lock);
seldrain(&tfd->tfd_sel);
knlist_destroy(&tfd->tfd_sel.si_note);
fp->f_ops = &badfileops;
mtx_destroy(&tfd->tfd_lock);
free(tfd, M_EPOLL);
return (0);
}
static int
timerfd_read(struct file *fp, struct uio *uio, struct ucred *active_cred,
int flags, struct thread *td)
{
struct timerfd *tfd;
timerfd_t count;
int error;
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
return (EINVAL);
if (uio->uio_resid < sizeof(timerfd_t))
return (EINVAL);
error = 0;
mtx_lock(&tfd->tfd_lock);
retry:
if (tfd->tfd_canceled) {
tfd->tfd_count = 0;
mtx_unlock(&tfd->tfd_lock);
return (ECANCELED);
}
if (tfd->tfd_count == 0) {
if ((fp->f_flag & FNONBLOCK) != 0) {
mtx_unlock(&tfd->tfd_lock);
return (EAGAIN);
}
error = mtx_sleep(&tfd->tfd_count, &tfd->tfd_lock, PCATCH, "ltfdrd", 0);
if (error == 0)
goto retry;
}
if (error == 0) {
count = tfd->tfd_count;
tfd->tfd_count = 0;
mtx_unlock(&tfd->tfd_lock);
error = uiomove(&count, sizeof(timerfd_t), uio);
} else
mtx_unlock(&tfd->tfd_lock);
return (error);
}
static int
timerfd_poll(struct file *fp, int events, struct ucred *active_cred,
struct thread *td)
{
struct timerfd *tfd;
int revents = 0;
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
return (POLLERR);
mtx_lock(&tfd->tfd_lock);
if ((events & (POLLIN|POLLRDNORM)) && tfd->tfd_count > 0)
revents |= events & (POLLIN|POLLRDNORM);
if (revents == 0)
selrecord(td, &tfd->tfd_sel);
mtx_unlock(&tfd->tfd_lock);
return (revents);
}
/*ARGSUSED*/
static int
timerfd_kqfilter(struct file *fp, struct knote *kn)
{
struct timerfd *tfd;
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL)
return (EINVAL);
if (kn->kn_filter == EVFILT_READ)
kn->kn_fop = &timerfd_rfiltops;
else
return (EINVAL);
kn->kn_hook = tfd;
knlist_add(&tfd->tfd_sel.si_note, kn, 0);
return (0);
}
static void
filt_timerfddetach(struct knote *kn)
{
struct timerfd *tfd = kn->kn_hook;
mtx_lock(&tfd->tfd_lock);
knlist_remove(&tfd->tfd_sel.si_note, kn, 1);
mtx_unlock(&tfd->tfd_lock);
}
/*ARGSUSED*/
static int
filt_timerfdread(struct knote *kn, long hint)
{
struct timerfd *tfd = kn->kn_hook;
return (tfd->tfd_count > 0);
}
/*ARGSUSED*/
static int
timerfd_stat(struct file *fp, struct stat *st, struct ucred *active_cred,
struct thread *td)
{
return (ENXIO);
}
/*ARGSUSED*/
static int
timerfd_fill_kinfo(struct file *fp, struct kinfo_file *kif, struct filedesc *fdp)
{
kif->kf_type = KF_TYPE_UNKNOWN;
return (0);
}
static void
linux_timerfd_clocktime(struct timerfd *tfd, struct timespec *ts)
{
if (tfd->tfd_clockid == CLOCK_REALTIME)
getnanotime(ts);
else /* CLOCK_MONOTONIC */
getnanouptime(ts);
}
static void
linux_timerfd_curval(struct timerfd *tfd, struct itimerspec *ots)
{
struct timespec cts;
linux_timerfd_clocktime(tfd, &cts);
*ots = tfd->tfd_time;
if (ots->it_value.tv_sec != 0 || ots->it_value.tv_nsec != 0) {
timespecsub(&ots->it_value, &cts);
if (ots->it_value.tv_sec < 0 ||
(ots->it_value.tv_sec == 0 &&
ots->it_value.tv_nsec == 0)) {
ots->it_value.tv_sec = 0;
ots->it_value.tv_nsec = 1;
}
}
}
int
linux_timerfd_gettime(struct thread *td, struct linux_timerfd_gettime_args *args)
{
cap_rights_t rights;
struct l_itimerspec lots;
struct itimerspec ots;
struct timerfd *tfd;
struct file *fp;
int error;
error = fget(td, args->fd, cap_rights_init(&rights, CAP_READ), &fp);
if (error != 0)
return (error);
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL) {
error = EINVAL;
goto out;
}
mtx_lock(&tfd->tfd_lock);
linux_timerfd_curval(tfd, &ots);
mtx_unlock(&tfd->tfd_lock);
error = native_to_linux_itimerspec(&lots, &ots);
if (error == 0)
error = copyout(&lots, args->old_value, sizeof(lots));
out:
fdrop(fp, td);
return (error);
}
int
linux_timerfd_settime(struct thread *td, struct linux_timerfd_settime_args *args)
{
struct l_itimerspec lots;
struct itimerspec nts, ots;
struct timespec cts, ts;
cap_rights_t rights;
struct timerfd *tfd;
struct timeval tv;
struct file *fp;
int error;
if ((args->flags & ~LINUX_TFD_SETTIME_FLAGS) != 0)
return (EINVAL);
error = copyin(args->new_value, &lots, sizeof(lots));
if (error != 0)
return (error);
error = linux_to_native_itimerspec(&nts, &lots);
if (error != 0)
return (error);
error = fget(td, args->fd, cap_rights_init(&rights, CAP_WRITE), &fp);
if (error != 0)
return (error);
tfd = fp->f_data;
if (fp->f_type != DTYPE_LINUXTFD || tfd == NULL) {
error = EINVAL;
goto out;
}
mtx_lock(&tfd->tfd_lock);
if (!timespecisset(&nts.it_value))
timespecclear(&nts.it_interval);
if (args->old_value != NULL)
linux_timerfd_curval(tfd, &ots);
tfd->tfd_time = nts;
if (timespecisset(&nts.it_value)) {
linux_timerfd_clocktime(tfd, &cts);
ts = nts.it_value;
if ((args->flags & LINUX_TFD_TIMER_ABSTIME) == 0) {
timespecadd(&tfd->tfd_time.it_value, &cts);
} else {
timespecsub(&ts, &cts);
}
TIMESPEC_TO_TIMEVAL(&tv, &ts);
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
linux_timerfd_expire, tfd);
tfd->tfd_canceled = false;
} else {
tfd->tfd_canceled = true;
callout_stop(&tfd->tfd_callout);
}
mtx_unlock(&tfd->tfd_lock);
if (args->old_value != NULL) {
error = native_to_linux_itimerspec(&lots, &ots);
if (error == 0)
error = copyout(&lots, args->old_value, sizeof(lots));
}
out:
fdrop(fp, td);
return (error);
}
static void
linux_timerfd_expire(void *arg)
{
struct timespec cts, ts;
struct timeval tv;
struct timerfd *tfd;
tfd = (struct timerfd *)arg;
linux_timerfd_clocktime(tfd, &cts);
if (timespeccmp(&cts, &tfd->tfd_time.it_value, >=)) {
if (timespecisset(&tfd->tfd_time.it_interval))
timespecadd(&tfd->tfd_time.it_value,
&tfd->tfd_time.it_interval);
else
/* single shot timer */
timespecclear(&tfd->tfd_time.it_value);
if (timespecisset(&tfd->tfd_time.it_value)) {
ts = tfd->tfd_time.it_value;
timespecsub(&ts, &cts);
TIMESPEC_TO_TIMEVAL(&tv, &ts);
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
linux_timerfd_expire, tfd);
}
tfd->tfd_count++;
KNOTE_LOCKED(&tfd->tfd_sel.si_note, 0);
selwakeup(&tfd->tfd_sel);
wakeup(&tfd->tfd_count);
} else if (timespecisset(&tfd->tfd_time.it_value)) {
ts = tfd->tfd_time.it_value;
timespecsub(&ts, &cts);
TIMESPEC_TO_TIMEVAL(&tv, &ts);
callout_reset(&tfd->tfd_callout, tvtohz(&tv),
linux_timerfd_expire, tfd);
}
}

View File

@ -57,4 +57,15 @@
#define LINUX_EFD_SEMAPHORE (1 << 0)
#define LINUX_TFD_TIMER_ABSTIME (1 << 0)
#define LINUX_TFD_TIMER_CANCEL_ON_SET (1 << 1)
#define LINUX_TFD_CLOEXEC LINUX_O_CLOEXEC
#define LINUX_TFD_NONBLOCK LINUX_O_NONBLOCK
#define LINUX_TFD_SHARED_FCNTL_FLAGS (LINUX_TFD_CLOEXEC \
|LINUX_TFD_NONBLOCK)
#define LINUX_TFD_CREATE_FLAGS LINUX_TFD_SHARED_FCNTL_FLAGS
#define LINUX_TFD_SETTIME_FLAGS (LINUX_TFD_TIMER_ABSTIME \
|LINUX_TFD_TIMER_CANCEL_ON_SET)
#endif /* !_LINUX_EVENT_H_ */

View File

@ -2290,8 +2290,9 @@ linux_pselect6(struct thread *td, struct linux_pselect6_args *args)
TIMEVAL_TO_TIMESPEC(&utv, &uts);
native_to_linux_timespec(&lts, &uts);
error = copyout(&lts, args->tsp, sizeof(lts));
error = native_to_linux_timespec(&lts, &uts);
if (error == 0)
error = copyout(&lts, args->tsp, sizeof(lts));
}
return (error);
@ -2343,8 +2344,9 @@ linux_ppoll(struct thread *td, struct linux_ppoll_args *args)
} else
timespecclear(&uts);
native_to_linux_timespec(&lts, &uts);
error = copyout(&lts, args->tsp, sizeof(lts));
error = native_to_linux_timespec(&lts, &uts);
if (error == 0)
error = copyout(&lts, args->tsp, sizeof(lts));
}
return (error);
@ -2438,7 +2440,9 @@ linux_sched_rr_get_interval(struct thread *td,
PROC_UNLOCK(tdt->td_proc);
if (error != 0)
return (error);
native_to_linux_timespec(&lts, &ts);
error = native_to_linux_timespec(&lts, &ts);
if (error != 0)
return (error);
return (copyout(&lts, uap->interval, sizeof(lts)));
}

View File

@ -303,7 +303,9 @@ struct l_statfs {
l_long f_ffree;
l_fsid_t f_fsid;
l_long f_namelen;
l_long f_spare[6];
l_long f_frsize;
l_long f_flags;
l_long f_spare[4];
};
#define LINUX_CODA_SUPER_MAGIC 0x73757245L
@ -371,6 +373,9 @@ bsd_to_linux_statfs(struct statfs *bsd_statfs, struct l_statfs *linux_statfs)
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
linux_statfs->f_namelen = MAXNAMLEN;
linux_statfs->f_frsize = bsd_statfs->f_bsize;
linux_statfs->f_flags = 0;
memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
return (0);
}
@ -415,6 +420,9 @@ bsd_to_linux_statfs64(struct statfs *bsd_statfs, struct l_statfs64 *linux_statfs
linux_statfs->f_fsid.val[0] = bsd_statfs->f_fsid.val[0];
linux_statfs->f_fsid.val[1] = bsd_statfs->f_fsid.val[1];
linux_statfs->f_namelen = MAXNAMLEN;
linux_statfs->f_frsize = bsd_statfs->f_bsize;
linux_statfs->f_flags = 0;
memset(linux_statfs->f_spare, 0, sizeof(linux_statfs->f_spare));
}
int

View File

@ -41,6 +41,7 @@ __KERNEL_RCSID(0, "$NetBSD: linux_time.c,v 1.14 2006/05/14 03:40:54 christos Exp
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/ucred.h>
#include <sys/limits.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/resourcevar.h>
@ -118,16 +119,21 @@ LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, unsupported_clockid, "int");
LIN_SDT_PROBE_DEFINE1(time, linux_clock_nanosleep, return, "int");
void
int
native_to_linux_timespec(struct l_timespec *ltp, struct timespec *ntp)
{
LIN_SDT_PROBE2(time, native_to_linux_timespec, entry, ltp, ntp);
#ifdef COMPAT_LINUX32
if (ntp->tv_sec > INT_MAX &&
sizeof(ltp->tv_sec) != sizeof(ntp->tv_sec))
return (EOVERFLOW);
#endif
ltp->tv_sec = ntp->tv_sec;
ltp->tv_nsec = ntp->tv_nsec;
LIN_SDT_PROBE0(time, native_to_linux_timespec, return);
return (0);
}
int
@ -147,6 +153,28 @@ linux_to_native_timespec(struct timespec *ntp, struct l_timespec *ltp)
return (0);
}
int
native_to_linux_itimerspec(struct l_itimerspec *ltp, struct itimerspec *ntp)
{
int error;
error = native_to_linux_timespec(&ltp->it_interval, &ntp->it_interval);
if (error == 0)
error = native_to_linux_timespec(&ltp->it_value, &ntp->it_interval);
return (error);
}
int
linux_to_native_itimerspec(struct itimerspec *ntp, struct l_itimerspec *ltp)
{
int error;
error = linux_to_native_timespec(&ntp->it_interval, &ltp->it_interval);
if (error == 0)
error = linux_to_native_timespec(&ntp->it_value, &ltp->it_value);
return (error);
}
int
linux_to_native_clockid(clockid_t *n, clockid_t l)
{
@ -322,8 +350,9 @@ linux_clock_gettime(struct thread *td, struct linux_clock_gettime_args *args)
LIN_SDT_PROBE1(time, linux_clock_gettime, return, error);
return (error);
}
native_to_linux_timespec(&lts, &tp);
error = native_to_linux_timespec(&lts, &tp);
if (error != 0)
return (error);
error = copyout(&lts, args->tp, sizeof lts);
if (error != 0)
LIN_SDT_PROBE1(time, linux_clock_gettime, copyout_error, error);
@ -450,8 +479,9 @@ linux_clock_getres(struct thread *td, struct linux_clock_getres_args *args)
LIN_SDT_PROBE1(time, linux_clock_getres, return, error);
return (error);
}
native_to_linux_timespec(&lts, &ts);
error = native_to_linux_timespec(&lts, &ts);
if (error != 0)
return (error);
error = copyout(&lts, args->tp, sizeof lts);
if (error != 0)
LIN_SDT_PROBE1(time, linux_clock_getres, copyout_error, error);
@ -490,7 +520,9 @@ linux_nanosleep(struct thread *td, struct linux_nanosleep_args *args)
}
error = kern_nanosleep(td, &rqts, rmtp);
if (args->rmtp != NULL) {
native_to_linux_timespec(&lrmts, rmtp);
error2 = native_to_linux_timespec(&lrmts, rmtp);
if (error2 != 0)
return (error2);
error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
if (error2 != 0) {
LIN_SDT_PROBE1(time, linux_nanosleep, copyout_error,
@ -553,7 +585,9 @@ linux_clock_nanosleep(struct thread *td, struct linux_clock_nanosleep_args *args
error = kern_nanosleep(td, &rqts, rmtp);
if (args->rmtp != NULL) {
/* XXX. Not for TIMER_ABSTIME */
native_to_linux_timespec(&lrmts, rmtp);
error2 = native_to_linux_timespec(&lrmts, rmtp);
if (error2 != 0)
return (error2);
error2 = copyout(&lrmts, args->rmtp, sizeof(lrmts));
if (error2 != 0) {
LIN_SDT_PROBE1(time, linux_clock_nanosleep,

View File

@ -111,10 +111,14 @@ struct l_itimerspec {
struct l_timespec it_value;
};
void native_to_linux_timespec(struct l_timespec *,
int native_to_linux_timespec(struct l_timespec *,
struct timespec *);
int linux_to_native_timespec(struct timespec *,
struct l_timespec *);
int linux_to_native_clockid(clockid_t *, clockid_t);
int native_to_linux_itimerspec(struct l_itimerspec *,
struct itimerspec *);
int linux_to_native_itimerspec(struct itimerspec *,
struct l_itimerspec *);
#endif /* _LINUX_TIMER_H */

View File

@ -35,6 +35,7 @@
#include <sys/types.h>
#include <sys/systm.h>
#include <sys/errno.h>
#include <sys/libkern.h>
#define BIT(nr) (1UL << (nr))
#define BIT_ULL(nr) (1ULL << (nr))
@ -43,6 +44,7 @@
#else
#define BITS_PER_LONG 32
#endif
#define BITMAP_FIRST_WORD_MASK(start) (~0UL << ((start) % BITS_PER_LONG))
#define BITMAP_LAST_WORD_MASK(n) (~0UL >> (BITS_PER_LONG - (n)))
#define BITS_TO_LONGS(n) howmany((n), BITS_PER_LONG)
@ -51,6 +53,12 @@
#define GENMASK(h, l) (((~0UL) >> (BITS_PER_LONG - (h) - 1)) & ((~0UL) << (l)))
#define BITS_PER_BYTE 8
#define hweight8(x) bitcount((uint8_t)(x))
#define hweight16(x) bitcount16(x)
#define hweight32(x) bitcount32(x)
#define hweight64(x) bitcount64(x)
#define hweight_long(x) bitcountl(x)
static inline int
__ffs(int mask)
{
@ -75,10 +83,15 @@ __flsl(long mask)
return (flsl(mask) - 1);
}
static inline int
fls64(uint64_t mask)
{
return (flsll(mask));
}
static inline uint32_t
ror32(uint32_t word, unsigned int shift)
{
return ((word >> shift) | (word << (32 - shift)));
}
@ -542,4 +555,12 @@ bitmap_equal(const unsigned long *pa,
return (1);
}
static inline uint64_t
sign_extend64(uint64_t value, int index)
{
uint8_t shift = 63 - index;
return ((int64_t)(value << shift) >> shift);
}
#endif /* _LINUX_BITOPS_H_ */

View File

@ -57,6 +57,7 @@ typedef unsigned int uint;
typedef unsigned gfp_t;
typedef uint64_t loff_t;
typedef vm_paddr_t resource_size_t;
typedef uint16_t __bitwise__ __sum16;
typedef u64 phys_addr_t;

View File

@ -1,13 +0,0 @@
# Makefile for syscall tables
#
# $FreeBSD$
all:
@echo "make sysent only"
sysent: svr4_sysent.c svr4_syscall.h svr4_proto.h
svr4_syscallnames.c svr4_sysent.c svr4_syscall.h svr4_proto.h: \
../../kern/makesyscalls.sh syscalls.master syscalls.conf
sh ../../kern/makesyscalls.sh syscalls.master syscalls.conf

View File

@ -1,38 +0,0 @@
This is a SysVR4 emulator derived from work done as part of the NetBSD
Project by Christos Zoulas. It has been ported to FreeBSD by Mark Newton.
To use it:
1. Choose one of:
a. Add "device streams" to your kernel config file and rebuild,
reboot; or
b. Build and install the streams module in /sys/modules/streams
2. Build and install the svr4 module in /sys/modules/svr4
3. Type "kldload svr4" to start it up.
4. Grab compat_sol26.tar.gz or compat_svr4.tar.gz from
http://www.freebsd.org/~newton/freebsd-svr4 and install them in
/compat/svr4
5. Run "sh SVR4_MAKEDEV all" in /compat/svr4/dev
6. Mount a Solaris/x86 v2.6 or v7 CD-ROM on /cdrom (also works with
v2.4 and v2.5.1, but you need different symlinks in /compat/svr4)
7. Brand any executables you want to run, and/or set the
kern.fallback_elf_brand sysctl to 'SVR4' to establish this as the
default emulator for unbranded executables.
8. See if your SysVR4 programs work.
It's early days yet, folks -- You'll probably have trouble getting 100%
functionality out of most things (specifically, poll() on a socket doesn't
look like it works at the moment, so Netscape doesn't work (among other
things)). Patches will be appreciated.
- Mark Newton
newton@atdot.dotat.org
$FreeBSD$

View File

@ -1,15 +0,0 @@
TO-DO list
----------
* svr4_getdents64() doesn't work properly in 'large' directories.
* signals are still suspect
* networking is notworking
* VM86 and USER_LDT are currently disabled (low-priority)
* Make SysV emulator use SysV shared memory support (duh)
$FreeBSD$

View File

@ -1,238 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994-1996 Søren Schmidt
* All rights reserved.
*
* Based heavily on /sys/kern/imgact_aout.c which is:
* Copyright (c) 1993, David Greenman
*
* 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
* in this position and unchanged.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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 <sys/param.h>
#include <sys/systm.h>
#include <sys/exec.h>
#include <sys/imgact.h>
#include <sys/imgact_aout.h>
#include <sys/kernel.h>
#include <sys/lock.h>
#include <sys/mman.h>
#include <sys/mutex.h>
#include <sys/proc.h>
#include <sys/racct.h>
#include <sys/resourcevar.h>
#include <sys/vnode.h>
#include <vm/vm.h>
#include <vm/vm_kern.h>
#include <vm/vm_param.h>
#include <vm/pmap.h>
#include <vm/vm_map.h>
#include <vm/vm_extern.h>
#include <compat/svr4/svr4.h>
static int exec_svr4_imgact(struct image_params *iparams);
static int
exec_svr4_imgact(imgp)
struct image_params *imgp;
{
const struct exec *a_out = (const struct exec *) imgp->image_header;
struct vmspace *vmspace;
vm_offset_t vmaddr;
unsigned long virtual_offset, file_offset;
unsigned long bss_size;
ssize_t aresid;
int error;
if (((a_out->a_magic >> 16) & 0xff) != 0x64)
return -1;
/*
* Set file/virtual offset based on a.out variant.
*/
switch ((int)(a_out->a_magic & 0xffff)) {
case 0413:
virtual_offset = 0;
file_offset = 1024;
break;
case 0314:
virtual_offset = 4096;
file_offset = 0;
break;
default:
return (-1);
}
bss_size = round_page(a_out->a_bss);
#ifdef DEBUG
printf("imgact: text: %08lx, data: %08lx, bss: %08lx\n", (u_long)a_out->a_text, (u_long)a_out->a_data, bss_size);
#endif
/*
* Check various fields in header for validity/bounds.
*/
if (a_out->a_entry < virtual_offset ||
a_out->a_entry >= virtual_offset + a_out->a_text ||
a_out->a_text & PAGE_MASK || a_out->a_data & PAGE_MASK)
return (-1);
/* text + data can't exceed file size */
if (a_out->a_data + a_out->a_text > imgp->attr->va_size)
return (EFAULT);
/*
* text/data/bss must not exceed limits
*/
PROC_LOCK(imgp->proc);
if (a_out->a_text > maxtsiz ||
a_out->a_data + bss_size > lim_cur_proc(imgp->proc, RLIMIT_DATA) ||
racct_set(imgp->proc, RACCT_DATA, a_out->a_data + bss_size) != 0) {
PROC_UNLOCK(imgp->proc);
return (ENOMEM);
}
PROC_UNLOCK(imgp->proc);
VOP_UNLOCK(imgp->vp, 0);
/*
* Destroy old process VM and create a new one (with a new stack)
*/
error = exec_new_vmspace(imgp, &svr4_sysvec);
if (error)
goto fail;
vmspace = imgp->proc->p_vmspace;
/*
* Check if file_offset page aligned,.
* Currently we cannot handle misalinged file offsets,
* and so we read in the entire image (what a waste).
*/
if (file_offset & PAGE_MASK) {
#ifdef DEBUG
printf("imgact: Non page aligned binary %lu\n", file_offset);
#endif
/*
* Map text+data+bss read/write/execute
*/
vmaddr = virtual_offset;
error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
a_out->a_text + a_out->a_data + bss_size, 0, VMFS_NO_SPACE,
VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
goto fail;
error = vn_rdwr(UIO_READ, imgp->vp, (void *)vmaddr, file_offset,
a_out->a_text + a_out->a_data, UIO_USERSPACE, 0,
curthread->td_ucred, NOCRED, &aresid, curthread);
if (error != 0)
goto fail;
if (aresid != 0) {
error = ENOEXEC;
goto fail;
}
/*
* remove write enable on the 'text' part
*/
error = vm_map_protect(&vmspace->vm_map,
vmaddr,
vmaddr + a_out->a_text,
VM_PROT_EXECUTE|VM_PROT_READ,
TRUE);
if (error)
goto fail;
}
else {
#ifdef DEBUG
printf("imgact: Page aligned binary %lu\n", file_offset);
#endif
/*
* Map text+data read/execute
*/
vmaddr = virtual_offset;
error = vm_mmap(&vmspace->vm_map, &vmaddr,
a_out->a_text + a_out->a_data,
VM_PROT_READ | VM_PROT_EXECUTE,
VM_PROT_ALL,
MAP_PRIVATE | MAP_FIXED,
OBJT_VNODE, imgp->vp, file_offset);
if (error)
goto fail;
#ifdef DEBUG
printf("imgact: startaddr=%08lx, length=%08lx\n", (u_long)vmaddr,
(u_long)a_out->a_text + a_out->a_data);
#endif
/*
* allow read/write of data
*/
error = vm_map_protect(&vmspace->vm_map,
vmaddr + a_out->a_text,
vmaddr + a_out->a_text + a_out->a_data,
VM_PROT_ALL,
FALSE);
if (error)
goto fail;
/*
* Allocate anon demand-zeroed area for uninitialized data
*/
if (bss_size != 0) {
vmaddr = virtual_offset + a_out->a_text + a_out->a_data;
error = vm_map_find(&vmspace->vm_map, NULL, 0, &vmaddr,
bss_size, 0, VMFS_NO_SPACE, VM_PROT_ALL, VM_PROT_ALL, 0);
if (error)
goto fail;
#ifdef DEBUG
printf("imgact: bssaddr=%08lx, length=%08lx\n",
(u_long)vmaddr, bss_size);
#endif
}
}
/* Fill in process VM information */
vmspace->vm_tsize = round_page(a_out->a_text) >> PAGE_SHIFT;
vmspace->vm_dsize = round_page(a_out->a_data + bss_size) >> PAGE_SHIFT;
vmspace->vm_taddr = (caddr_t)virtual_offset;
vmspace->vm_daddr = (caddr_t)virtual_offset + a_out->a_text;
/* Fill in image_params */
imgp->interpreted = 0;
imgp->entry_addr = a_out->a_entry;
imgp->proc->p_sysent = &svr4_sysvec;
fail:
vn_lock(imgp->vp, LK_EXCLUSIVE | LK_RETRY);
return (error);
}
/*
* Tell kern_execve.c about it, with a little help from the linker.
*/
struct execsw svr4_execsw = { exec_svr4_imgact, "svr4 ELF" };
EXEC_SET(execsw_set, svr4_execsw);

View File

@ -1,46 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1996 Christos Zoulas.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christos Zoulas.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_ACL_H_
#define _SVR4_ACL_H_
typedef struct svr4_aclent {
int a_type;
svr4_uid_t a_id;
svr4_o_mode_t a_perm;
} svr4_aclent_t;
#define SVR4_SYS_GETACL 1
#define SVR4_SYS_SETACL 2
#define SVR4_SYS_GETACLCNT 3
#endif /* !_SVR4_ACL_H_ */

View File

@ -1,53 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_DIRENT_H_
#define _SVR4_DIRENT_H_
#define SVR4_MAXNAMLEN 512
struct svr4_dirent {
svr4_ino_t d_ino;
svr4_off_t d_off;
u_short d_reclen;
char d_name[SVR4_MAXNAMLEN + 1];
};
struct svr4_dirent64 {
svr4_ino64_t d_ino;
svr4_off64_t d_off;
u_short d_reclen;
char d_name[SVR4_MAXNAMLEN + 1];
};
#define SVR4_NAMEOFF(dp) ((char *)&(dp)->d_name - (char *)dp)
#define SVR4_RECLEN(de,namlen) ALIGN((SVR4_NAMEOFF(de) + (namlen) + 1))
#endif /* !_SVR4_DIRENT_H_ */

View File

@ -1,172 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_ERRNO_H_
#define _SVR4_ERRNO_H_
#define SVR4_EPERM 1
#define SVR4_ENOENT 2
#define SVR4_ESRCH 3
#define SVR4_EINTR 4
#define SVR4_EIO 5
#define SVR4_ENXIO 6
#define SVR4_E2BIG 7
#define SVR4_ENOEXEC 8
#define SVR4_EBADF 9
#define SVR4_ECHILD 10
#define SVR4_EAGAIN 11
#define SVR4_ENOMEM 12
#define SVR4_EACCES 13
#define SVR4_EFAULT 14
#define SVR4_ENOTBLK 15
#define SVR4_EBUSY 16
#define SVR4_EEXIST 17
#define SVR4_EXDEV 18
#define SVR4_ENODEV 19
#define SVR4_ENOTDIR 20
#define SVR4_EISDIR 21
#define SVR4_EINVAL 22
#define SVR4_ENFILE 23
#define SVR4_EMFILE 24
#define SVR4_ENOTTY 25
#define SVR4_ETXTBSY 26
#define SVR4_EFBIG 27
#define SVR4_ENOSPC 28
#define SVR4_ESPIPE 29
#define SVR4_EROFS 30
#define SVR4_EMLINK 31
#define SVR4_EPIPE 32
#define SVR4_EDOM 33
#define SVR4_ERANGE 34
#define SVR4_ENOMSG 35
#define SVR4_EIDRM 36
#define SVR4_ECHRNG 37
#define SVR4_EL2NSYNC 38
#define SVR4_EL3HLT 39
#define SVR4_EL3RST 40
#define SVR4_ELNRNG 41
#define SVR4_EUNATCH 42
#define SVR4_ENOCSI 43
#define SVR4_EL2HLT 44
#define SVR4_EDEADLK 45
#define SVR4_ENOLCK 46
#define SVR4_EBADE 50
#define SVR4_EBADR 51
#define SVR4_EXFULL 52
#define SVR4_ENOANO 53
#define SVR4_EBADRQC 54
#define SVR4_EBADSLT 55
#define SVR4_EDEADLOCK 56
#define SVR4_EBFONT 57
#define SVR4_ENOSTR 60
#define SVR4_ENODATA 61
#define SVR4_ETIME 62
#define SVR4_ENOSR 63
#define SVR4_ENONET 64
#define SVR4_ENOPKG 65
#define SVR4_EREMOTE 66
#define SVR4_ENOLINK 67
#define SVR4_EADV 68
#define SVR4_ESRMNT 69
#define SVR4_ECOMM 70
#define SVR4_EPROTO 71
#define SVR4_EMULTIHOP 74
#define SVR4_EBADMSG 77
#define SVR4_ENAMETOOLONG 78
#define SVR4_EOVERFLOW 79
#define SVR4_ENOTUNIQ 80
#define SVR4_EBADFD 81
#define SVR4_EREMCHG 82
#define SVR4_ELIBACC 83
#define SVR4_ELIBBAD 84
#define SVR4_ELIBSCN 85
#define SVR4_ELIBMAX 86
#define SVR4_ELIBEXEC 87
#define SVR4_EILSEQ 88
#define SVR4_ENOSYS 89
#define SVR4_ELOOP 90
#define SVR4_ERESTART 91
#define SVR4_ESTRPIPE 92
#define SVR4_ENOTEMPTY 93
#define SVR4_EUSERS 94
#define SVR4_ENOTSOCK 95
#define SVR4_EDESTADDRREQ 96
#define SVR4_EMSGSIZE 97
#define SVR4_EPROTOTYPE 98
#define SVR4_ENOPROTOOPT 99
#define SVR4_EPROTONOSUPPORT 120
#define SVR4_ESOCKTNOSUPPORT 121
#define SVR4_EOPNOTSUPP 122
#define SVR4_EPFNOSUPPORT 123
#define SVR4_EAFNOSUPPORT 124
#define SVR4_EADDRINUSE 125
#define SVR4_EADDRNOTAVAIL 126
#define SVR4_ENETDOWN 127
#define SVR4_ENETUNREACH 128
#define SVR4_ENETRESET 129
#define SVR4_ECONNABORTED 130
#define SVR4_ECONNRESET 131
#define SVR4_ENOBUFS 132
#define SVR4_EISCONN 133
#define SVR4_ENOTCONN 134
#define SVR4_EUCLEAN 135
#define SVR4_ENOTNAM 137
#define SVR4_ENAVAIL 138
#define SVR4_EISNAM 139
#define SVR4_EREMOTEIO 140
#define SVR4_EINIT 141
#define SVR4_EREMDEV 142
#define SVR4_ESHUTDOWN 143
#define SVR4_ETOOMANYREFS 144
#define SVR4_ETIMEDOUT 145
#define SVR4_ECONNREFUSED 146
#define SVR4_EHOSTDOWN 147
#define SVR4_EHOSTUNREACH 148
#define SVR4_EWOULDBLOCK SVR4_EAGAIN
#define SVR4_EALREADY 149
#define SVR4_EINPROGRESS 150
#define SVR4_ESTALE 151
#define SVR4_EIORESID 500
/*
* These ones are not translated...
*/
#define SVR4_EPROCLIM SVR4_ENOSYS
#define SVR4_EDQUOT SVR4_ENOSYS
#define SVR4_EBADRPC SVR4_ENOSYS
#define SVR4_ERPCMISMATCH SVR4_ENOSYS
#define SVR4_EPROGUNAVAIL SVR4_ENOSYS
#define SVR4_EPROGMISMATCH SVR4_ENOSYS
#define SVR4_EPROCUNAVAIL SVR4_ENOSYS
#define SVR4_EFTYPE SVR4_ENOSYS
#define SVR4_EAUTH SVR4_ENOSYS
#define SVR4_ENEEDAUTH SVR4_ENOSYS
#endif /* !_SVR4_ERRNO_H_ */

View File

@ -1,70 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_EXEC_H_
#define _SVR4_EXEC_H_
#ifdef SVR4_COMPAT_SOLARIS2
# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 12 / sizeof(char *))
#else
# define SVR4_AUX_ARGSIZ (sizeof(AuxInfo) * 8 / sizeof(char *))
#endif
#if 0
/* Don't think we need all this NetBSD stuff */
/*
* The following is horrible; there must be a better way. I need to
* play with brk(2) a bit more.
*/
#ifdef __i386__
/*
* I cannot load the interpreter after the data segment because brk(2)
* breaks. I have to load it somewhere before. Programs start at
* 0x08000000 so I load the interpreter far before.
*/
#define SVR4_INTERP_ADDR 0x01000000
#endif
#ifdef sparc
/*
* Here programs load at 0x00010000, so I load the interpreter far after
* the end of the data segment.
*/
#define SVR4_INTERP_ADDR 0x10000000
#endif
#ifndef SVR4_INTERP_ADDR
# define SVR4_INTERP_ADDR 0
#endif
#endif
/*void svr4_setregs(struct thread *, struct exec_package *, u_long);*/
#endif /* !_SVR4_EXEC_H_ */

View File

@ -1,732 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994, 1997 Christos Zoulas.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. All advertising materials mentioning features or use of this software
* must display the following acknowledgement:
* This product includes software developed by Christos Zoulas.
* 4. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR 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 <sys/param.h>
#include <sys/capsicum.h>
#include <sys/systm.h>
#include <sys/file.h>
#include <sys/filedesc.h>
/*#include <sys/ioctl.h>*/
#include <sys/lock.h>
#include <sys/malloc.h>
#include <sys/mount.h>
#include <sys/mutex.h>
#include <sys/namei.h>
#include <sys/priv.h>
#include <sys/proc.h>
#include <sys/stat.h>
#include <sys/syscallsubr.h>
#include <sys/unistd.h>
#include <sys/vnode.h>
#include <sys/sysproto.h>
#include <compat/svr4/svr4.h>
#include <compat/svr4/svr4_types.h>
#include <compat/svr4/svr4_signal.h>
#include <compat/svr4/svr4_proto.h>
#include <compat/svr4/svr4_util.h>
#include <compat/svr4/svr4_fcntl.h>
#include <security/mac/mac_framework.h>
static int svr4_to_bsd_flags(int);
static u_long svr4_to_bsd_cmd(u_long);
static int fd_revoke(struct thread *, int);
static int fd_truncate(struct thread *, int, struct flock *);
static int bsd_to_svr4_flags(int);
static void bsd_to_svr4_flock(struct flock *, struct svr4_flock *);
static void svr4_to_bsd_flock(struct svr4_flock *, struct flock *);
static void bsd_to_svr4_flock64(struct flock *, struct svr4_flock64 *);
static void svr4_to_bsd_flock64(struct svr4_flock64 *, struct flock *);
static u_long
svr4_to_bsd_cmd(cmd)
u_long cmd;
{
switch (cmd) {
case SVR4_F_DUPFD:
return F_DUPFD;
case SVR4_F_DUP2FD:
return F_DUP2FD;
case SVR4_F_GETFD:
return F_GETFD;
case SVR4_F_SETFD:
return F_SETFD;
case SVR4_F_GETFL:
return F_GETFL;
case SVR4_F_SETFL:
return F_SETFL;
case SVR4_F_GETLK:
return F_GETLK;
case SVR4_F_SETLK:
return F_SETLK;
case SVR4_F_SETLKW:
return F_SETLKW;
default:
return -1;
}
}
static int
svr4_to_bsd_flags(l)
int l;
{
int r = 0;
r |= (l & SVR4_O_RDONLY) ? O_RDONLY : 0;
r |= (l & SVR4_O_WRONLY) ? O_WRONLY : 0;
r |= (l & SVR4_O_RDWR) ? O_RDWR : 0;
r |= (l & SVR4_O_NDELAY) ? O_NONBLOCK : 0;
r |= (l & SVR4_O_APPEND) ? O_APPEND : 0;
r |= (l & SVR4_O_SYNC) ? O_FSYNC : 0;
r |= (l & SVR4_O_NONBLOCK) ? O_NONBLOCK : 0;
r |= (l & SVR4_O_PRIV) ? O_EXLOCK : 0;
r |= (l & SVR4_O_CREAT) ? O_CREAT : 0;
r |= (l & SVR4_O_TRUNC) ? O_TRUNC : 0;
r |= (l & SVR4_O_EXCL) ? O_EXCL : 0;
r |= (l & SVR4_O_NOCTTY) ? O_NOCTTY : 0;
return r;
}
static int
bsd_to_svr4_flags(l)
int l;
{
int r = 0;
r |= (l & O_RDONLY) ? SVR4_O_RDONLY : 0;
r |= (l & O_WRONLY) ? SVR4_O_WRONLY : 0;
r |= (l & O_RDWR) ? SVR4_O_RDWR : 0;
r |= (l & O_NDELAY) ? SVR4_O_NONBLOCK : 0;
r |= (l & O_APPEND) ? SVR4_O_APPEND : 0;
r |= (l & O_FSYNC) ? SVR4_O_SYNC : 0;
r |= (l & O_NONBLOCK) ? SVR4_O_NONBLOCK : 0;
r |= (l & O_EXLOCK) ? SVR4_O_PRIV : 0;
r |= (l & O_CREAT) ? SVR4_O_CREAT : 0;
r |= (l & O_TRUNC) ? SVR4_O_TRUNC : 0;
r |= (l & O_EXCL) ? SVR4_O_EXCL : 0;
r |= (l & O_NOCTTY) ? SVR4_O_NOCTTY : 0;
return r;
}
static void
bsd_to_svr4_flock(iflp, oflp)
struct flock *iflp;
struct svr4_flock *oflp;
{
switch (iflp->l_type) {
case F_RDLCK:
oflp->l_type = SVR4_F_RDLCK;
break;
case F_WRLCK:
oflp->l_type = SVR4_F_WRLCK;
break;
case F_UNLCK:
oflp->l_type = SVR4_F_UNLCK;
break;
default:
oflp->l_type = -1;
break;
}
oflp->l_whence = (short) iflp->l_whence;
oflp->l_start = (svr4_off_t) iflp->l_start;
oflp->l_len = (svr4_off_t) iflp->l_len;
oflp->l_sysid = 0;
oflp->l_pid = (svr4_pid_t) iflp->l_pid;
}
static void
svr4_to_bsd_flock(iflp, oflp)
struct svr4_flock *iflp;
struct flock *oflp;
{
switch (iflp->l_type) {
case SVR4_F_RDLCK:
oflp->l_type = F_RDLCK;
break;
case SVR4_F_WRLCK:
oflp->l_type = F_WRLCK;
break;
case SVR4_F_UNLCK:
oflp->l_type = F_UNLCK;
break;
default:
oflp->l_type = -1;
break;
}
oflp->l_whence = iflp->l_whence;
oflp->l_start = (off_t) iflp->l_start;
oflp->l_len = (off_t) iflp->l_len;
oflp->l_pid = (pid_t) iflp->l_pid;
oflp->l_sysid = iflp->l_sysid;
}
static void
bsd_to_svr4_flock64(iflp, oflp)
struct flock *iflp;
struct svr4_flock64 *oflp;
{
switch (iflp->l_type) {
case F_RDLCK:
oflp->l_type = SVR4_F_RDLCK;
break;
case F_WRLCK:
oflp->l_type = SVR4_F_WRLCK;
break;
case F_UNLCK:
oflp->l_type = SVR4_F_UNLCK;
break;
default:
oflp->l_type = -1;
break;
}
oflp->l_whence = (short) iflp->l_whence;
oflp->l_start = (svr4_off64_t) iflp->l_start;
oflp->l_len = (svr4_off64_t) iflp->l_len;
oflp->l_sysid = iflp->l_sysid;
oflp->l_pid = (svr4_pid_t) iflp->l_pid;
}
static void
svr4_to_bsd_flock64(iflp, oflp)
struct svr4_flock64 *iflp;
struct flock *oflp;
{
switch (iflp->l_type) {
case SVR4_F_RDLCK:
oflp->l_type = F_RDLCK;
break;
case SVR4_F_WRLCK:
oflp->l_type = F_WRLCK;
break;
case SVR4_F_UNLCK:
oflp->l_type = F_UNLCK;
break;
default:
oflp->l_type = -1;
break;
}
oflp->l_whence = iflp->l_whence;
oflp->l_start = (off_t) iflp->l_start;
oflp->l_len = (off_t) iflp->l_len;
oflp->l_pid = (pid_t) iflp->l_pid;
}
static int
fd_revoke(td, fd)
struct thread *td;
int fd;
{
struct vnode *vp;
struct mount *mp;
struct vattr vattr;
cap_rights_t rights;
int error, *retval;
retval = td->td_retval;
/*
* If we ever want to support Capsicum on SVR4 processes (unlikely)
* or FreeBSD grows a native frevoke() (more likely), we will need a
* CAP_FREVOKE here.
*
* In the meantime, use CAP_ALL(): if a SVR4 process wants to
* do an frevoke(), it needs to do it on either a regular file
* descriptor or a fully-privileged capability (which is effectively
* the same as a non-capability-restricted file descriptor).
*/
CAP_ALL(&rights);
if ((error = fgetvp(td, fd, &rights, &vp)) != 0)
return (error);
if (vp->v_type != VCHR && vp->v_type != VBLK) {
error = EINVAL;
goto out;
}
#ifdef MAC
vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
error = mac_vnode_check_revoke(td->td_ucred, vp);
VOP_UNLOCK(vp, 0);
if (error)
goto out;
#endif
if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0)
goto out;
if (td->td_ucred->cr_uid != vattr.va_uid &&
(error = priv_check(td, PRIV_VFS_ADMIN)) != 0)
goto out;
if ((error = vn_start_write(vp, &mp, V_WAIT | PCATCH)) != 0)
goto out;
if (vcount(vp) > 1)
VOP_REVOKE(vp, REVOKEALL);
vn_finished_write(mp);
out:
vrele(vp);
return error;
}
static int
fd_truncate(td, fd, flp)
struct thread *td;
int fd;
struct flock *flp;
{
off_t start, length;
struct file *fp;
struct vnode *vp;
struct vattr vattr;
int error, *retval;
struct ftruncate_args ft;
cap_rights_t rights;
retval = td->td_retval;
/*
* We only support truncating the file.
*/
error = fget(td, fd, cap_rights_init(&rights, CAP_FTRUNCATE), &fp);
if (error != 0)
return (error);
vp = fp->f_vnode;
if (fp->f_type != DTYPE_VNODE || vp->v_type == VFIFO) {
fdrop(fp, td);
return ESPIPE;
}
if ((error = VOP_GETATTR(vp, &vattr, td->td_ucred)) != 0) {
fdrop(fp, td);
return error;
}
length = vattr.va_size;
switch (flp->l_whence) {
case SEEK_CUR:
start = fp->f_offset + flp->l_start;
break;
case SEEK_END:
start = flp->l_start + length;
break;
case SEEK_SET:
start = flp->l_start;
break;
default:
fdrop(fp, td);
return EINVAL;
}
if (start + flp->l_len < length) {
/* We don't support free'ing in the middle of the file */
fdrop(fp, td);
return EINVAL;
}
ft.fd = fd;
ft.length = start;
error = sys_ftruncate(td, &ft);
fdrop(fp, td);
return (error);
}
int
svr4_sys_open(td, uap)
struct thread *td;
struct svr4_sys_open_args *uap;
{
struct proc *p = td->td_proc;
char *newpath;
int bsd_flags, error, retval;
CHECKALTEXIST(td, uap->path, &newpath);
bsd_flags = svr4_to_bsd_flags(uap->flags);
error = kern_openat(td, AT_FDCWD, newpath, UIO_SYSSPACE, bsd_flags,
uap->mode);
free(newpath, M_TEMP);
if (error) {
/* uprintf("svr4_open(%s, 0x%0x, 0%o): %d\n", uap->path,
uap->flags, uap->mode, error);*/
return error;
}
retval = td->td_retval[0];
PROC_LOCK(p);
if (!(bsd_flags & O_NOCTTY) && SESS_LEADER(p) &&
!(p->p_flag & P_CONTROLT)) {
#if defined(NOTYET)
cap_rights_t rights;
struct file *fp;
error = fget(td, retval,
cap_rights_init(&rights, CAP_IOCTL), &fp);
PROC_UNLOCK(p);
/*
* we may have lost a race the above open() and
* another thread issuing a close()
*/
if (error)
return (EBADF); /* XXX: correct errno? */
/* ignore any error, just give it a try */
if (fp->f_type == DTYPE_VNODE)
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td->td_ucred,
td);
fdrop(fp, td);
} else {
PROC_UNLOCK(p);
}
#else
}
PROC_UNLOCK(p);
#endif
return error;
}
int
svr4_sys_open64(td, uap)
struct thread *td;
struct svr4_sys_open64_args *uap;
{
return svr4_sys_open(td, (struct svr4_sys_open_args *)uap);
}
int
svr4_sys_creat(td, uap)
struct thread *td;
struct svr4_sys_creat_args *uap;
{
char *newpath;
int error;
CHECKALTEXIST(td, uap->path, &newpath);
error = kern_openat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
O_WRONLY | O_CREAT | O_TRUNC, uap->mode);
free(newpath, M_TEMP);
return (error);
}
int
svr4_sys_creat64(td, uap)
struct thread *td;
struct svr4_sys_creat64_args *uap;
{
return svr4_sys_creat(td, (struct svr4_sys_creat_args *)uap);
}
int
svr4_sys_llseek(td, uap)
struct thread *td;
struct svr4_sys_llseek_args *uap;
{
struct lseek_args ap;
ap.fd = uap->fd;
#if BYTE_ORDER == BIG_ENDIAN
ap.offset = (((u_int64_t) uap->offset1) << 32) |
uap->offset2;
#else
ap.offset = (((u_int64_t) uap->offset2) << 32) |
uap->offset1;
#endif
ap.whence = uap->whence;
return sys_lseek(td, &ap);
}
int
svr4_sys_access(td, uap)
struct thread *td;
struct svr4_sys_access_args *uap;
{
char *newpath;
int error;
CHECKALTEXIST(td, uap->path, &newpath);
error = kern_accessat(td, AT_FDCWD, newpath, UIO_SYSSPACE,
0, uap->amode);
free(newpath, M_TEMP);
return (error);
}
#if defined(NOTYET)
int
svr4_sys_pread(td, uap)
struct thread *td;
struct svr4_sys_pread_args *uap;
{
struct pread_args pra;
/*
* Just translate the args structure and call the NetBSD
* pread(2) system call (offset type is 64-bit in NetBSD).
*/
pra.fd = uap->fd;
pra.buf = uap->buf;
pra.nbyte = uap->nbyte;
pra.offset = uap->off;
return pread(td, &pra);
}
#endif
#if defined(NOTYET)
int
svr4_sys_pread64(td, v, retval)
struct thread *td;
void *v;
register_t *retval;
{
struct svr4_sys_pread64_args *uap = v;
struct sys_pread_args pra;
/*
* Just translate the args structure and call the NetBSD
* pread(2) system call (offset type is 64-bit in NetBSD).
*/
pra.fd = uap->fd;
pra.buf = uap->buf;
pra.nbyte = uap->nbyte;
pra.offset = uap->off;
return (sys_pread(td, &pra, retval));
}
#endif /* NOTYET */
#if defined(NOTYET)
int
svr4_sys_pwrite(td, uap)
struct thread *td;
struct svr4_sys_pwrite_args *uap;
{
struct pwrite_args pwa;
/*
* Just translate the args structure and call the NetBSD
* pwrite(2) system call (offset type is 64-bit in NetBSD).
*/
pwa.fd = uap->fd;
pwa.buf = uap->buf;
pwa.nbyte = uap->nbyte;
pwa.offset = uap->off;
return pwrite(td, &pwa);
}
#endif
#if defined(NOTYET)
int
svr4_sys_pwrite64(td, v, retval)
struct thread *td;
void *v;
register_t *retval;
{
struct svr4_sys_pwrite64_args *uap = v;
struct sys_pwrite_args pwa;
/*
* Just translate the args structure and call the NetBSD
* pwrite(2) system call (offset type is 64-bit in NetBSD).
*/
pwa.fd = uap->fd;
pwa.buf = uap->buf;
pwa.nbyte = uap->nbyte;
pwa.offset = uap->off;
return (sys_pwrite(td, &pwa, retval));
}
#endif /* NOTYET */
int
svr4_sys_fcntl(td, uap)
struct thread *td;
struct svr4_sys_fcntl_args *uap;
{
int cmd, error, *retval;
retval = td->td_retval;
cmd = svr4_to_bsd_cmd(uap->cmd);
switch (cmd) {
case F_DUPFD:
case F_DUP2FD:
case F_GETFD:
case F_SETFD:
return (kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg));
case F_GETFL:
error = kern_fcntl(td, uap->fd, cmd, (intptr_t)uap->arg);
if (error)
return (error);
*retval = bsd_to_svr4_flags(*retval);
return (error);
case F_SETFL:
{
/*
* we must save the O_ASYNC flag, as that is
* handled by ioctl(_, I_SETSIG, _) emulation.
*/
int flags;
DPRINTF(("Setting flags %p\n", uap->arg));
error = kern_fcntl(td, uap->fd, F_GETFL, 0);
if (error)
return (error);
flags = *retval;
flags &= O_ASYNC;
flags |= svr4_to_bsd_flags((u_long) uap->arg);
return (kern_fcntl(td, uap->fd, F_SETFL, flags));
}
case F_GETLK:
case F_SETLK:
case F_SETLKW:
{
struct svr4_flock ifl;
struct flock fl;
error = copyin(uap->arg, &ifl, sizeof (ifl));
if (error)
return (error);
svr4_to_bsd_flock(&ifl, &fl);
error = kern_fcntl(td, uap->fd, cmd, (intptr_t)&fl);
if (error || cmd != F_GETLK)
return (error);
bsd_to_svr4_flock(&fl, &ifl);
return (copyout(&ifl, uap->arg, sizeof (ifl)));
}
case -1:
switch (uap->cmd) {
case SVR4_F_FREESP:
{
struct svr4_flock ifl;
struct flock fl;
error = copyin(uap->arg, &ifl,
sizeof ifl);
if (error)
return error;
svr4_to_bsd_flock(&ifl, &fl);
return fd_truncate(td, uap->fd, &fl);
}
case SVR4_F_GETLK64:
case SVR4_F_SETLK64:
case SVR4_F_SETLKW64:
{
struct svr4_flock64 ifl;
struct flock fl;
switch (uap->cmd) {
case SVR4_F_GETLK64:
cmd = F_GETLK;
break;
case SVR4_F_SETLK64:
cmd = F_SETLK;
break;
case SVR4_F_SETLKW64:
cmd = F_SETLKW;
break;
}
error = copyin(uap->arg, &ifl,
sizeof (ifl));
if (error)
return (error);
svr4_to_bsd_flock64(&ifl, &fl);
error = kern_fcntl(td, uap->fd, cmd,
(intptr_t)&fl);
if (error || cmd != F_GETLK)
return (error);
bsd_to_svr4_flock64(&fl, &ifl);
return (copyout(&ifl, uap->arg,
sizeof (ifl)));
}
case SVR4_F_FREESP64:
{
struct svr4_flock64 ifl;
struct flock fl;
error = copyin(uap->arg, &ifl,
sizeof ifl);
if (error)
return error;
svr4_to_bsd_flock64(&ifl, &fl);
return fd_truncate(td, uap->fd, &fl);
}
case SVR4_F_REVOKE:
return fd_revoke(td, uap->fd);
default:
return ENOSYS;
}
default:
return ENOSYS;
}
}

View File

@ -1,134 +0,0 @@
/*-
* Copyright (c) 1998 Mark Newton
* Copyright (c) 1994 Christos Zoulas
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. The name of the author may not be used to endorse or promote products
* derived from this software without specific prior written permission
*
* THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
* IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
* IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
* NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
* THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
* THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*
* $FreeBSD$
*/
#ifndef _SVR4_FCNTL_H_
#define _SVR4_FCNTL_H_
#include <compat/svr4/svr4_types.h>
#include <sys/fcntl.h>
#define SVR4_O_RDONLY 0x0000
#define SVR4_O_WRONLY 0x0001
#define SVR4_O_RDWR 0x0002
#define SVR4_O_ACCMODE 0x0003
#define SVR4_O_NDELAY 0x0004
#define SVR4_O_APPEND 0x0008
#define SVR4_O_SYNC 0x0010
#define SVR4_O_NONBLOCK 0x0080
#define SVR4_O_CREAT 0x0100
#define SVR4_O_TRUNC 0x0200
#define SVR4_O_EXCL 0x0400
#define SVR4_O_NOCTTY 0x0800
#define SVR4_O_PRIV 0x1000
#define SVR4_FD_CLOEXEC 1
#define SVR4_F_DUPFD 0
#define SVR4_F_GETFD 1
#define SVR4_F_SETFD 2
#define SVR4_F_GETFL 3
#define SVR4_F_SETFL 4
#define SVR4_F_GETLK_SVR3 5
#define SVR4_F_SETLK 6
#define SVR4_F_SETLKW 7
#define SVR4_F_CHKFL 8
#define SVR4_F_DUP2FD 9
#define SVR4_F_ALLOCSP 10
#define SVR4_F_FREESP 11
#define SVR4_F_ISSTREAM 13
#define SVR4_F_GETLK 14
#define SVR4_F_PRIV 15
#define SVR4_F_NPRIV 16
#define SVR4_F_QUOTACTL 17
#define SVR4_F_BLOCKS 18
#define SVR4_F_BLKSIZE 19
#define SVR4_F_RSETLK 20
#define SVR4_F_RGETLK 21
#define SVR4_F_RSETLKW 22
#define SVR4_F_GETOWN 23
#define SVR4_F_SETOWN 24
#define SVR4_F_REVOKE 25
#define SVR4_F_HASREMOTELOCKS 26
#define SVR4_F_FREESP64 27
#define SVR4_F_GETLK64 33
#define SVR4_F_SETLK64 34
#define SVR4_F_SETLKW64 35
#define SVR4_F_SHARE 40
#define SVR4_F_UNSHARE 41
#define SVR4_F_CHSIZE_XENIX 0x6000
#define SVR4_F_RDCHK_XENIX 0x6001
#define SVR4_F_LK_UNLCK_XENIX 0x6300
#define SVR4_F_LK_LOCK_XENIX 0x7200
#define SVR4_F_LK_NBLCK_XENIX 0x6200
#define SVR4_F_LK_RLCK_XENIX 0x7100
#define SVR4_F_LK_NBRLCK_XENIX 0x6100
#define SVR4_LK_CMDTYPE(x) (((x) >> 12) & 0x7)
#define SVR4_LK_LCKTYPE(x) (((x) >> 8) & 0x7)
#define SVR4_F_RDLCK 1
#define SVR4_F_WRLCK 2
#define SVR4_F_UNLCK 3
struct svr4_flock_svr3 {
short l_type;
short l_whence;
svr4_off_t l_start;
svr4_off_t l_len;
short l_sysid;
svr4_o_pid_t l_pid;
};
struct svr4_flock {
short l_type;
short l_whence;
svr4_off_t l_start;
svr4_off_t l_len;
long l_sysid;
svr4_pid_t l_pid;
long pad[4];
};
struct svr4_flock64 {
short l_type;
short l_whence;
svr4_off64_t l_start;
svr4_off64_t l_len;
long l_sysid;
svr4_pid_t l_pid;
long pad[4];
};
#endif /* !_SVR4_FCNTL_H_ */

Some files were not shown because too many files have changed in this diff Show More